Merge "msm: mdss: dsi: separate out DBA functionality from DSI"

This commit is contained in:
Linux Build Service Account 2015-06-20 18:58:09 -07:00 committed by Gerrit - the friendly Code Review server
commit 14a88e8b92
8 changed files with 557 additions and 307 deletions

View File

@ -36,6 +36,7 @@ obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_util.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_edid.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_cec_abstract.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_dba_utils.o
obj-$(CONFIG_FB_MSM_MDSS_EDP_PANEL) += mdss_edp.o
obj-$(CONFIG_FB_MSM_MDSS_EDP_PANEL) += mdss_edp_aux.o

View File

@ -0,0 +1,465 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <video/msm_dba.h>
#include <linux/switch.h>
#include "mdss_dba_utils.h"
#include "mdss_hdmi_edid.h"
#include "mdss_fb.h"
struct mdss_dba_utils_data {
struct msm_dba_ops ops;
bool hpd_state;
bool audio_switch_registered;
bool display_switch_registered;
struct switch_dev sdev_display;
struct switch_dev sdev_audio;
struct kobject *kobj;
struct mdss_panel_info *pinfo;
void *dba_data;
void *edid_data;
u8 *edid_buf;
u32 edid_buf_size;
};
static struct mdss_dba_utils_data *mdss_dba_utils_get_data(
struct device *device)
{
struct msm_fb_data_type *mfd;
struct mdss_panel_info *pinfo;
struct fb_info *fbi;
struct mdss_dba_utils_data *udata = NULL;
if (!device) {
pr_err("Invalid device data\n");
goto end;
}
fbi = dev_get_drvdata(device);
if (!fbi) {
pr_err("Invalid fbi data\n");
goto end;
}
mfd = (struct msm_fb_data_type *)fbi->par;
if (!mfd) {
pr_err("Invalid mfd data\n");
goto end;
}
pinfo = mfd->panel_info;
if (!pinfo) {
pr_err("Invalid pinfo data\n");
goto end;
}
udata = pinfo->dba_data;
end:
return udata;
}
static void mdss_dba_utils_send_display_notification(
struct mdss_dba_utils_data *udata, int val)
{
int state = 0;
if (!udata) {
pr_err("invalid input\n");
return;
}
if (!udata->display_switch_registered) {
pr_err("display switch not registered\n");
return;
}
state = udata->sdev_display.state;
switch_set_state(&udata->sdev_display, val);
pr_debug("cable state %s %d\n",
udata->sdev_display.state == state ?
"is same" : "switched to",
udata->sdev_display.state);
}
static void mdss_dba_utils_send_audio_notification(
struct mdss_dba_utils_data *udata, int val)
{
int state = 0;
if (!udata) {
pr_err("invalid input\n");
return;
}
if (!udata->audio_switch_registered) {
pr_err("audio switch not registered\n");
return;
}
state = udata->sdev_audio.state;
switch_set_state(&udata->sdev_audio, val);
pr_debug("audio state %s %d\n",
udata->sdev_audio.state == state ?
"is same" : "switched to",
udata->sdev_audio.state);
}
static ssize_t mdss_dba_utils_sysfs_rda_connected(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct mdss_dba_utils_data *udata = NULL;
if (!dev) {
pr_err("invalid device\n");
return -EINVAL;
}
udata = mdss_dba_utils_get_data(dev);
if (!udata) {
pr_err("invalid input\n");
return -EINVAL;
}
ret = snprintf(buf, PAGE_SIZE, "%d\n", udata->hpd_state);
pr_debug("'%d'\n", udata->hpd_state);
return ret;
}
static DEVICE_ATTR(connected, S_IRUGO,
mdss_dba_utils_sysfs_rda_connected, NULL);
static struct attribute *mdss_dba_utils_fs_attrs[] = {
&dev_attr_connected.attr,
NULL,
};
static struct attribute_group mdss_dba_utils_fs_attrs_group = {
.attrs = mdss_dba_utils_fs_attrs,
};
static int mdss_dba_utils_sysfs_create(struct kobject *kobj)
{
int rc;
if (!kobj) {
pr_err("invalid input\n");
return -ENODEV;
}
rc = sysfs_create_group(kobj, &mdss_dba_utils_fs_attrs_group);
if (rc) {
pr_err("failed, rc=%d\n", rc);
return rc;
}
return 0;
}
static void mdss_dba_utils_sysfs_remove(struct kobject *kobj)
{
if (!kobj) {
pr_err("invalid input\n");
return;
}
sysfs_remove_group(kobj, &mdss_dba_utils_fs_attrs_group);
}
static void mdss_dba_utils_dba_cb(void *data, enum msm_dba_callback_event event)
{
int ret = -EINVAL;
struct mdss_dba_utils_data *udata = data;
bool pluggable = false;
if (!udata) {
pr_err("Invalid data\n");
return;
}
pr_debug("event: %d\n", event);
if (udata->pinfo)
pluggable = udata->pinfo->is_pluggable;
switch (event) {
case MSM_DBA_CB_HPD_CONNECT:
if (udata->ops.get_raw_edid) {
ret = udata->ops.get_raw_edid(udata->dba_data,
udata->edid_buf_size, udata->edid_buf, 0);
if (!ret)
hdmi_edid_parser(udata->edid_data);
else
pr_err("failed to get edid%d\n", ret);
}
if (pluggable) {
mdss_dba_utils_send_display_notification(udata, 1);
mdss_dba_utils_send_audio_notification(udata, 1);
} else {
mdss_dba_utils_video_on(udata, udata->pinfo);
}
udata->hpd_state = true;
break;
case MSM_DBA_CB_HPD_DISCONNECT:
if (pluggable) {
mdss_dba_utils_send_audio_notification(udata, 0);
mdss_dba_utils_send_display_notification(udata, 0);
} else {
mdss_dba_utils_video_off(udata);
}
udata->hpd_state = false;
break;
default:
break;
}
}
/**
* mdss_dba_utils_video_on() - Allow clients to switch on the video
* @data: DBA utils instance which was allocated during registration
* @pinfo: detailed panel information like x, y, porch values etc
*
* This API is used to power on the video on device registered
* with DBA.
*
* Return: returns the result of the video on call on device.
*/
int mdss_dba_utils_video_on(void *data, struct mdss_panel_info *pinfo)
{
struct mdss_dba_utils_data *ud = data;
struct msm_dba_video_cfg video_cfg;
int ret = -EINVAL;
if (!ud || !pinfo) {
pr_err("invalid input\n");
goto end;
}
memset(&video_cfg, 0, sizeof(video_cfg));
video_cfg.h_active = pinfo->xres;
video_cfg.v_active = pinfo->yres;
video_cfg.h_front_porch = pinfo->lcdc.h_front_porch;
video_cfg.v_front_porch = pinfo->lcdc.v_front_porch;
video_cfg.h_back_porch = pinfo->lcdc.h_back_porch;
video_cfg.v_back_porch = pinfo->lcdc.v_back_porch;
video_cfg.h_pulse_width = pinfo->lcdc.h_pulse_width;
video_cfg.v_pulse_width = pinfo->lcdc.v_pulse_width;
video_cfg.pclk_khz = pinfo->clk_rate / 1000;
if (ud->ops.video_on)
ret = ud->ops.video_on(ud->dba_data, true, &video_cfg, 0);
end:
return ret;
}
/**
* mdss_dba_utils_video_off() - Allow clients to switch off the video
* @data: DBA utils instance which was allocated during registration
*
* This API is used to power off the video on device registered
* with DBA.
*
* Return: returns the result of the video off call on device.
*/
int mdss_dba_utils_video_off(void *data)
{
struct mdss_dba_utils_data *ud = data;
int ret = -EINVAL;
if (!ud) {
pr_err("invalid input\n");
goto end;
}
if (ud->ops.video_on)
ret = ud->ops.video_on(ud->dba_data, false, NULL, 0);
end:
return ret;
}
/**
* mdss_dba_utils_init() - Allow clients to register with DBA utils
* @uid: Initialization data for registration.
*
* This API lets the client to register with DBA Utils module.
* This allocate utils' instance and register with DBA (Display
* Bridge Abstract). Creates sysfs nodes and switch nodes to interact
* with other modules. Also registers with EDID parser to parse
* the EDID buffer.
*
* Return: Instance of DBA utils which needs to be sent as parameter
* when calling DBA utils APIs.
*/
void *mdss_dba_utils_init(struct mdss_dba_utils_init_data *uid)
{
struct hdmi_edid_init_data edid_init_data;
struct mdss_dba_utils_data *udata = NULL;
struct msm_dba_reg_info info;
int ret = 0;
if (!uid) {
pr_err("invalid input\n");
ret = -EINVAL;
goto error;
}
udata = kzalloc(sizeof(*udata), GFP_KERNEL);
if (!udata) {
pr_err("Not enough Memory\n");
ret = -ENOMEM;
goto error;
}
memset(&edid_init_data, 0, sizeof(edid_init_data));
memset(&info, 0, sizeof(info));
/* initialize DBA registration data */
strlcpy(info.client_name, uid->client_name, MSM_DBA_CLIENT_NAME_LEN);
strlcpy(info.chip_name, uid->chip_name, MSM_DBA_CHIP_NAME_MAX_LEN);
info.instance_id = uid->instance_id;
info.cb = mdss_dba_utils_dba_cb;
info.cb_data = udata;
/* register client with DBA and get device's ops*/
if (IS_ENABLED(CONFIG_MSM_DBA)) {
udata->dba_data = msm_dba_register_client(&info, &udata->ops);
if (IS_ERR_OR_NULL(udata->dba_data)) {
pr_err("ds not configured\n");
ret = PTR_ERR(udata->dba_data);
goto error;
}
} else {
pr_err("DBA not enabled\n");
ret = -ENODEV;
goto error;
}
/* create sysfs nodes for other modules to intract with utils */
ret = mdss_dba_utils_sysfs_create(uid->kobj);
if (ret) {
pr_err("sysfs creation failed\n");
goto error;
}
/* keep init data for future use */
udata->kobj = uid->kobj;
udata->pinfo = uid->pinfo;
/* create switch device to update display modules */
udata->sdev_display.name = "bridge_display";
ret = switch_dev_register(&udata->sdev_display);
if (ret) {
pr_err("display switch registration failed\n");
goto error;
}
udata->display_switch_registered = true;
/* create switch device to update audio modules */
udata->sdev_audio.name = "hdmi_audio";
ret = switch_dev_register(&udata->sdev_audio);
if (ret) {
pr_err("audio switch registration failed\n");
goto error;
}
udata->audio_switch_registered = true;
/* Initialize EDID feature */
edid_init_data.kobj = uid->kobj;
/* register with edid module for parsing edid buffer */
udata->edid_data = hdmi_edid_init(&edid_init_data);
if (!udata->edid_data) {
pr_err("edid parser init failed\n");
ret = -ENODEV;
goto error;
}
/* update edid data to retrieve it back in edid parser */
if (uid->pinfo)
uid->pinfo->edid_data = udata->edid_data;
/* get edid buffer from edid parser */
udata->edid_buf = edid_init_data.buf;
udata->edid_buf_size = edid_init_data.buf_size;
/* power on downstream device */
if (udata->ops.power_on) {
ret = udata->ops.power_on(udata->dba_data, true, 0);
if (ret)
goto error;
}
return udata;
error:
mdss_dba_utils_deinit(udata);
return ERR_PTR(ret);
}
/**
* mdss_dba_utils_deinit() - Allow clients to de-register with DBA utils
* @data: DBA utils data that was allocated during registration.
*
* This API will release all the resources allocated during registration
* and delete the DBA utils instance.
*/
void mdss_dba_utils_deinit(void *data)
{
struct mdss_dba_utils_data *udata = data;
if (!udata) {
pr_err("invalid input\n");
return;
}
if (udata->edid_data)
hdmi_edid_deinit(udata->edid_data);
if (udata->pinfo)
udata->pinfo->edid_data = NULL;
if (udata->audio_switch_registered)
switch_dev_unregister(&udata->sdev_audio);
if (udata->display_switch_registered)
switch_dev_unregister(&udata->sdev_display);
if (udata->kobj)
mdss_dba_utils_sysfs_remove(udata->kobj);
if (IS_ENABLED(CONFIG_MSM_DBA)) {
if (!IS_ERR_OR_NULL(udata->dba_data))
msm_dba_deregister_client(udata->dba_data);
}
kfree(udata);
}

View File

@ -0,0 +1,45 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MDSS_DBA_UTILS__
#define __MDSS_DBA_UTILS__
#include <linux/types.h>
#include "mdss_panel.h"
/**
* struct mdss_dba_utils_init_data - Init data for registering with DBA utils.
* @kobj: An instance of Kobject for sysfs creation
* @instance_id: Instance ID of device registered with DBA
* @chip_name: Name of the device registered with DBA
* @client_name: Name of the client registering with DBA
* @pinfo: Detailed panel information
*
* This structure's instance is needed to be passed as parameter
* to register API to let the DBA utils module configure and
* allocate an instance of DBA utils for the client.
*/
struct mdss_dba_utils_init_data {
struct kobject *kobj;
u32 instance_id;
char *chip_name;
char *client_name;
struct mdss_panel_info *pinfo;
};
int mdss_dba_utils_video_on(void *data, struct mdss_panel_info *pinfo);
int mdss_dba_utils_video_off(void *data);
void *mdss_dba_utils_init(struct mdss_dba_utils_init_data *init_data);
void mdss_dba_utils_deinit(void *data);
#endif /* __MDSS_DBA_UTILS__ */

View File

@ -29,6 +29,7 @@
#include "mdss_panel.h"
#include "mdss_dsi.h"
#include "mdss_debug.h"
#include "mdss_dba_utils.h"
#define XO_CLK_RATE 19200000
@ -38,9 +39,6 @@ static struct mdss_dsi_data *mdss_dsi_res;
static int mdss_dsi_pinctrl_set_state(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
bool active);
static void mdss_dsi_send_audio_notification(
struct mdss_dsi_ctrl_pdata *ctrl_pdata, int val);
static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl(u32 ctrl_id)
{
if (ctrl_id >= DSI_CTRL_MAX || !mdss_dsi_res)
@ -1361,10 +1359,6 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
__func__);
goto error;
}
if (ctrl_pdata->ds_registered)
mdss_dsi_send_audio_notification(
ctrl_pdata, 1);
}
ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT;
}
@ -1446,10 +1440,6 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
pr_err("%s: Panel OFF failed\n", __func__);
goto error;
}
if (ctrl_pdata->ds_registered)
mdss_dsi_send_audio_notification(
ctrl_pdata, 0);
}
ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
}
@ -1937,272 +1927,13 @@ static int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata)
return rc;
}
static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata_from_panel_data(
struct mdss_panel_data *mpd)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
if (!mpd) {
pr_err("%s: Invalid panel data\n", __func__);
goto end;
}
ctrl_pdata = container_of(mpd, struct mdss_dsi_ctrl_pdata,
panel_data);
end:
return ctrl_pdata;
}
static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata_from_sysfs_dev(
struct device *device)
{
struct msm_fb_data_type *mfd = NULL;
struct mdss_panel_data *panel_data = NULL;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct fb_info *fbi;
if (!device) {
pr_err("%s: Invalid device data\n", __func__);
goto end;
}
fbi = dev_get_drvdata(device);
if (!fbi) {
pr_err("%s: Invalid fbi data\n", __func__);
goto end;
}
mfd = (struct msm_fb_data_type *)fbi->par;
if (!mfd) {
pr_err("%s: Invalid mfd data\n", __func__);
goto end;
}
panel_data = dev_get_platdata(&mfd->pdev->dev);
if (!panel_data) {
pr_err("%s: Invalid panel data\n", __func__);
goto end;
}
ctrl_pdata = mdss_dsi_get_drvdata_from_panel_data(panel_data);
end:
return ctrl_pdata;
}
static ssize_t mdss_dsi_sysfs_rda_connected(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
if (!dev) {
DEV_ERR("%s: invalid device\n", __func__);
return -EINVAL;
}
ctrl_pdata = mdss_dsi_get_drvdata_from_sysfs_dev(dev);
if (!ctrl_pdata) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
ret = snprintf(buf, PAGE_SIZE, "%d\n", ctrl_pdata->hpd_state);
pr_debug("%s: '%d'\n", __func__, ctrl_pdata->hpd_state);
return ret;
}
static DEVICE_ATTR(connected, S_IRUGO, mdss_dsi_sysfs_rda_connected, NULL);
static struct attribute *mdss_dsi_fs_attrs[] = {
&dev_attr_connected.attr,
NULL,
};
static struct attribute_group mdss_dsi_fs_attrs_group = {
.attrs = mdss_dsi_fs_attrs,
};
static int mdss_dsi_sysfs_create(struct kobject *kobj)
{
int rc;
if (!kobj) {
DEV_ERR("%s: invalid input\n", __func__);
return -ENODEV;
}
rc = sysfs_create_group(kobj, &mdss_dsi_fs_attrs_group);
if (rc) {
pr_err("%s: failed, rc=%d\n", __func__, rc);
return rc;
}
return 0;
}
static inline void mdss_dsi_send_cable_notification(
struct mdss_dsi_ctrl_pdata *ctrl_pdata, int val)
{
int state = 0;
if (!ctrl_pdata) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
state = ctrl_pdata->sdev.state;
switch_set_state(&ctrl_pdata->sdev, val);
DEV_INFO("%s: cable state %s %d\n", __func__,
ctrl_pdata->sdev.state == state ?
"is same" : "switched to",
ctrl_pdata->sdev.state);
}
static void mdss_dsi_send_audio_notification(
struct mdss_dsi_ctrl_pdata *ctrl_pdata, int val)
{
int state = 0;
if (!ctrl_pdata) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
state = ctrl_pdata->sdev_audio.state;
switch_set_state(&ctrl_pdata->sdev_audio, val);
DEV_INFO("%s: audio state %s %d\n", __func__,
ctrl_pdata->sdev_audio.state == state ?
"is same" : "switched to",
ctrl_pdata->sdev_audio.state);
}
static void mdss_dsi_dba_cb(void *data, enum msm_dba_callback_event event)
{
int ret = -EINVAL;
struct mdss_dsi_ctrl_pdata *ctrl_pdata =
(struct mdss_dsi_ctrl_pdata *) data;
if (!ctrl_pdata) {
pr_err("%s: Invalid data\n", __func__);
return;
}
switch (event) {
case MSM_DBA_CB_HPD_CONNECT:
ctrl_pdata->hpd_state = true;
if (ctrl_pdata->dba_ops.get_raw_edid)
ret = ctrl_pdata->dba_ops.get_raw_edid(
ctrl_pdata->dba_data,
ctrl_pdata->edid_buf_size,
ctrl_pdata->edid_buf, 0);
if (!ret)
hdmi_edid_parser(ctrl_pdata->edid_data);
mdss_dsi_send_cable_notification(ctrl_pdata, 1);
break;
case MSM_DBA_CB_HPD_DISCONNECT:
mdss_dsi_send_cable_notification(ctrl_pdata, 0);
ctrl_pdata->hpd_state = false;
break;
default:
break;
}
}
static void mdss_dsi_ctrl_init_dba(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct hdmi_edid_init_data edid_init_data;
struct fb_info *fbi;
msm_dba_cb dba_cb = mdss_dsi_dba_cb;
if (!ctrl_pdata) {
pr_err("%s: Invalid ctrl data\n", __func__);
goto end;
}
fbi = ctrl_pdata->fbi;
if (!fbi) {
pr_err("%s: Invalid fbi data\n", __func__);
goto end;
}
strlcpy(ctrl_pdata->dba_info.client_name, "dsi",
MSM_DBA_CLIENT_NAME_LEN);
strlcpy(ctrl_pdata->dba_info.chip_name, "adv7533",
MSM_DBA_CHIP_NAME_MAX_LEN);
ctrl_pdata->dba_info.instance_id = 0;
ctrl_pdata->dba_info.cb = dba_cb;
ctrl_pdata->dba_info.cb_data = ctrl_pdata;
ctrl_pdata->dba_data = msm_dba_register_client(
&ctrl_pdata->dba_info,
&ctrl_pdata->dba_ops);
if (IS_ERR_OR_NULL(ctrl_pdata->dba_data)) {
pr_err("%s: ds not configured\n", __func__);
goto end;
}
if (mdss_dsi_sysfs_create(&fbi->dev->kobj)) {
pr_err("%s:sysfs creation failed\n",
__func__);
goto end;
}
ctrl_pdata->sdev.name = "dsi";
if (switch_dev_register(&ctrl_pdata->sdev) < 0) {
pr_err("%s: DSI switch registration failed\n",
__func__);
goto end;
}
ctrl_pdata->sdev_audio.name = "bridge_audio";
if (switch_dev_register(&ctrl_pdata->sdev_audio) < 0) {
pr_err("%s: audio switch registration failed\n",
__func__);
goto end;
}
/* Initialize EDID feature */
edid_init_data.kobj = &fbi->dev->kobj;
edid_init_data.ds_data = NULL;
edid_init_data.id = fbi->node;
ctrl_pdata->edid_data = hdmi_edid_init(&edid_init_data);
if (!ctrl_pdata->edid_data) {
pr_err("%s: edid parser init failed\n", __func__);
goto end;
}
ctrl_pdata->panel_data.panel_info.edid_data = ctrl_pdata->edid_data;
/* get edid buffer from edid parser */
ctrl_pdata->edid_buf = edid_init_data.buf;
ctrl_pdata->edid_buf_size = edid_init_data.buf_size;
if (ctrl_pdata->dba_ops.power_on)
ctrl_pdata->dba_ops.power_on(ctrl_pdata->dba_data,
true, 0);
ctrl_pdata->ds_registered = true;
end:
return;
}
static void mdss_dsi_dba_work(struct work_struct *work)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct delayed_work *dw = to_delayed_work(work);
struct mdss_dba_utils_init_data utils_init_data;
struct mdss_panel_info *pinfo;
ctrl_pdata = container_of(dw, struct mdss_dsi_ctrl_pdata, dba_work);
if (!ctrl_pdata) {
@ -2210,7 +1941,24 @@ static void mdss_dsi_dba_work(struct work_struct *work)
return;
}
mdss_dsi_ctrl_init_dba(ctrl_pdata);
pinfo = &ctrl_pdata->panel_data.panel_info;
if (!pinfo) {
pr_err("%s: invalid ctrl data\n", __func__);
return;
}
memset(&utils_init_data, 0, sizeof(utils_init_data));
utils_init_data.chip_name = "adv7533";
utils_init_data.client_name = "dsi";
utils_init_data.instance_id = 0;
utils_init_data.kobj = ctrl_pdata->kobj;
utils_init_data.pinfo = pinfo;
pinfo->dba_data = mdss_dba_utils_init(&utils_init_data);
if (!IS_ERR_OR_NULL(pinfo->dba_data))
ctrl_pdata->ds_registered = true;
}
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
@ -2218,6 +1966,7 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
{
int rc = 0;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct fb_info *fbi;
int power_state;
u32 mode;
@ -2325,10 +2074,15 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
case MDSS_EVENT_FB_REGISTERED:
mdss_dsi_debugfs_init(ctrl_pdata);
ctrl_pdata->fbi = (struct fb_info *)arg;
fbi = (struct fb_info *)arg;
if (!fbi || !fbi->dev)
break;
queue_delayed_work(ctrl_pdata->workq, &ctrl_pdata->dba_work,
HZ);
ctrl_pdata->kobj = &fbi->dev->kobj;
if (IS_ENABLED(CONFIG_MSM_DBA))
queue_delayed_work(ctrl_pdata->workq,
&ctrl_pdata->dba_work, HZ);
break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
@ -2620,8 +2374,18 @@ static void mdss_dsi_res_deinit(struct platform_device *pdev)
}
for (i = 0; i < DSI_CTRL_MAX; i++) {
if (dsi_res->ctrl_pdata[i])
if (dsi_res->ctrl_pdata[i]) {
if (dsi_res->ctrl_pdata[i]->ds_registered) {
struct mdss_panel_info *pinfo =
&dsi_res->ctrl_pdata[i]->
panel_data.panel_info;
if (pinfo)
mdss_dba_utils_deinit(pinfo->dba_data);
}
devm_kfree(&pdev->dev, dsi_res->ctrl_pdata[i]);
}
}
sdata = dsi_res->shared_data;

View File

@ -19,12 +19,9 @@
#include <linux/irqreturn.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio.h>
#include <linux/switch.h>
#include <video/msm_dba.h>
#include "mdss_panel.h"
#include "mdss_dsi_cmd.h"
#include "mdss_hdmi_edid.h"
#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
@ -461,21 +458,9 @@ struct mdss_dsi_ctrl_pdata {
struct mdss_dsi_debugfs_info *debugfs_info;
bool dfps_status; /* dynamic refresh status */
struct switch_dev sdev;
bool hpd_state;
bool ds_registered;
struct switch_dev sdev_audio;
struct msm_dba_reg_info dba_info;
struct msm_dba_ops dba_ops;
struct msm_dba_video_cfg dba_video_cfg;
void *dba_data;
void *edid_data;
u8 *edid_buf;
u32 edid_buf_size;
struct fb_info *fbi;
struct kobject *kobj;
struct workqueue_struct *workq;
struct delayed_work dba_work;

View File

@ -23,6 +23,7 @@
#include <linux/err.h>
#include "mdss_dsi.h"
#include "mdss_dba_utils.h"
#define DT_CMD_HDR 6
#define MIN_REFRESH_RATE 48
@ -677,13 +678,8 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
if (on_cmds->cmd_cnt)
mdss_dsi_panel_cmds_send(ctrl, on_cmds);
if (ctrl->ds_registered) {
if (ctrl->dba_ops.video_on)
ret = ctrl->dba_ops.video_on(
ctrl->dba_data, true,
&ctrl->dba_video_cfg, 0);
}
if (ctrl->ds_registered)
mdss_dba_utils_video_on(pinfo->dba_data, pinfo);
end:
pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
pr_debug("%s:-\n", __func__);

View File

@ -452,6 +452,7 @@ struct mdss_panel_info {
bool is_pluggable;
void *edid_data;
void *dba_data;
char panel_name[MDSS_MAX_PANEL_LEN];
struct mdss_mdp_pp_tear_check te;

View File

@ -567,15 +567,8 @@ struct msm_dba_ops {
* chip. If Successful, this will return a pointer that should be used as a
* handle for all subsequent function calls.
*/
#ifdef CONFIG_MSM_DBA
void *msm_dba_register_client(struct msm_dba_reg_info *info,
struct msm_dba_ops *ops);
#else
static inline void *msm_dba_register_client(struct msm_dba_reg_info *info,
struct msm_dba_ops *ops) {
return NULL;
}
#endif
/**
* msm_dba_deregister_client() - Allows client to de-register with the driver.