msm: Bringup 2 instances of ADV7533 for 8996
Bringup 2 instances of ADV7533 for 8996. Change all register writes from constant to pdata variables. Move the DBA init from mdss_dsi.c to mdss_dsi_panel.c. Change-Id: Ib0fc9f7c2348efa04a44bc021cb50973e90d7f22 Signed-off-by: Siddharth Zaveri <szaveri@codeaurora.org> [cip@codeaurora.org: Removed spurious drivers/video/msm/Makefile change] Signed-off-by: Clarence Ip <cip@codeaurora.org>
This commit is contained in:
parent
8acce572a5
commit
4698f91320
8 changed files with 533 additions and 428 deletions
|
@ -2051,249 +2051,6 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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_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,
|
||||
sizeof(ctrl_pdata->edid_buf),
|
||||
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;
|
||||
}
|
||||
|
||||
/* Initialize EDID feature */
|
||||
edid_init_data.kobj = &fbi->dev->kobj;
|
||||
edid_init_data.ds_data = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ctrl_pdata = container_of(dw, struct mdss_dsi_ctrl_pdata, dba_work);
|
||||
if (!ctrl_pdata) {
|
||||
pr_err("%s: invalid ctrl data\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mdss_dsi_ctrl_init_dba(ctrl_pdata);
|
||||
}
|
||||
|
||||
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
|
||||
int event, void *arg)
|
||||
{
|
||||
|
@ -2414,11 +2171,6 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
|
|||
break;
|
||||
case MDSS_EVENT_FB_REGISTERED:
|
||||
mdss_dsi_debugfs_init(ctrl_pdata);
|
||||
|
||||
ctrl_pdata->fbi = (struct fb_info *)arg;
|
||||
|
||||
queue_delayed_work(ctrl_pdata->workq, &ctrl_pdata->dba_work,
|
||||
HZ);
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: unhandled event=%d\n", __func__, event);
|
||||
|
@ -2600,7 +2352,8 @@ exit:
|
|||
return dsi_pan_node;
|
||||
}
|
||||
|
||||
static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev)
|
||||
static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev,
|
||||
int ndx)
|
||||
{
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
|
||||
char panel_cfg[MDSS_MAX_PANEL_LEN];
|
||||
|
@ -2627,7 +2380,7 @@ static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata);
|
||||
rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, ndx);
|
||||
if (rc) {
|
||||
pr_err("%s: dsi panel init failed\n", __func__);
|
||||
of_node_put(dsi_pan_node);
|
||||
|
@ -2857,7 +2610,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
dsi_pan_node = mdss_dsi_config_panel(pdev);
|
||||
dsi_pan_node = mdss_dsi_config_panel(pdev, index);
|
||||
if (!dsi_pan_node) {
|
||||
pr_err("%s: panel configuration failed\n", __func__);
|
||||
return -EINVAL;
|
||||
|
@ -2918,16 +2671,6 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
|
|||
}
|
||||
disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
|
||||
}
|
||||
|
||||
ctrl_pdata->workq = create_workqueue("mdss_dsi_dba");
|
||||
if (!ctrl_pdata->workq) {
|
||||
pr_err("%s: Error creating workqueue\n", __func__);
|
||||
rc = -EPERM;
|
||||
goto error_pan_node;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&ctrl_pdata->dba_work, mdss_dsi_dba_work);
|
||||
|
||||
pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
|
||||
|
||||
if (index == 0)
|
||||
|
@ -3406,10 +3149,6 @@ static int mdss_dsi_ctrl_remove(struct platform_device *pdev)
|
|||
msm_dss_iounmap(&ctrl_pdata->phy_io);
|
||||
msm_dss_iounmap(&ctrl_pdata->ctrl_io);
|
||||
mdss_dsi_debugfs_cleanup(ctrl_pdata);
|
||||
|
||||
if (ctrl_pdata->workq)
|
||||
destroy_workqueue(ctrl_pdata->workq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -512,7 +512,6 @@ struct mdss_dsi_ctrl_pdata {
|
|||
|
||||
struct dsi_err_container err_cont;
|
||||
|
||||
bool dfps_status; /* dynamic refresh status */
|
||||
struct switch_dev sdev;
|
||||
bool hpd_state;
|
||||
bool ds_registered;
|
||||
|
@ -622,7 +621,8 @@ void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl);
|
|||
u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
|
||||
char cmd1, void (*fxn)(int), char *rbuf, int len);
|
||||
int mdss_dsi_panel_init(struct device_node *node,
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata);
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
||||
int ndx);
|
||||
int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
||||
struct mdss_panel_timing *timing);
|
||||
|
||||
|
|
|
@ -716,6 +716,10 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
|
|||
ret = ctrl->dba_ops.video_on(
|
||||
ctrl->dba_data, true,
|
||||
&ctrl->dba_video_cfg, 0);
|
||||
if (ret) {
|
||||
pr_err("%s: video on failed for chip %s\n",
|
||||
__func__, ctrl->dba_info.chip_name);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -2147,9 +2151,12 @@ static int mdss_dsi_panel_timing_from_dt(struct device_node *np,
|
|||
{
|
||||
u32 tmp;
|
||||
u64 tmp64;
|
||||
int rc, i, len;
|
||||
int rc, i, len, num_lanes;
|
||||
const char *data;
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
|
||||
pinfo = &panel_data->panel_info;
|
||||
|
||||
ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
|
||||
panel_data);
|
||||
|
@ -2211,6 +2218,35 @@ static int mdss_dsi_panel_timing_from_dt(struct device_node *np,
|
|||
"qcom,mdss-dsi-panel-clockrate", (u32 *)&tmp64);
|
||||
pt->timing.clk_rate = !rc ? tmp64 : 0;
|
||||
|
||||
/* Update timing parameter to DBA structure*/
|
||||
ctrl_pdata->dba_video_cfg.h_active =
|
||||
pt->timing.xres;
|
||||
ctrl_pdata->dba_video_cfg.h_front_porch =
|
||||
pt->timing.h_front_porch;
|
||||
ctrl_pdata->dba_video_cfg.h_back_porch =
|
||||
pt->timing.h_back_porch;
|
||||
ctrl_pdata->dba_video_cfg.h_pulse_width =
|
||||
pt->timing.h_pulse_width;
|
||||
ctrl_pdata->dba_video_cfg.v_active =
|
||||
pt->timing.yres;
|
||||
ctrl_pdata->dba_video_cfg.v_front_porch =
|
||||
pt->timing.v_front_porch;
|
||||
ctrl_pdata->dba_video_cfg.v_back_porch =
|
||||
pt->timing.v_back_porch;
|
||||
ctrl_pdata->dba_video_cfg.v_pulse_width =
|
||||
pt->timing.v_pulse_width;
|
||||
|
||||
num_lanes = 0;
|
||||
if (pinfo->mipi.data_lane0)
|
||||
num_lanes++;
|
||||
if (pinfo->mipi.data_lane1)
|
||||
num_lanes++;
|
||||
if (pinfo->mipi.data_lane2)
|
||||
num_lanes++;
|
||||
if (pinfo->mipi.data_lane3)
|
||||
num_lanes++;
|
||||
ctrl_pdata->dba_video_cfg.num_of_input_lanes = num_lanes;
|
||||
|
||||
data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
|
||||
if ((!data) || (len != 12)) {
|
||||
pr_err("%s:%d, Unable to read Phy timing settings",
|
||||
|
@ -2565,8 +2601,121 @@ error:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
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_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,
|
||||
sizeof(ctrl_pdata->edid_buf),
|
||||
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,
|
||||
int ndx)
|
||||
{
|
||||
struct hdmi_edid_init_data edid_init_data;
|
||||
msm_dba_cb dba_cb = mdss_dsi_dba_cb;
|
||||
|
||||
if (!ctrl_pdata) {
|
||||
pr_err("%s: Invalid ctrl data\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
snprintf(ctrl_pdata->dba_info.client_name, MSM_DBA_CLIENT_NAME_LEN,
|
||||
"dsi-%d", ndx);
|
||||
|
||||
strlcpy(ctrl_pdata->dba_info.chip_name, "adv7533",
|
||||
MSM_DBA_CHIP_NAME_MAX_LEN);
|
||||
|
||||
ctrl_pdata->dba_info.instance_id = ndx;
|
||||
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, %p\n", __func__,
|
||||
ctrl_pdata->dba_data);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctrl_pdata->sdev.name = ctrl_pdata->dba_info.client_name;
|
||||
if (switch_dev_register(&ctrl_pdata->sdev) < 0) {
|
||||
pr_err("%s: DSI switch registration failed\n",
|
||||
__func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
memset(&edid_init_data, 0x00, sizeof(edid_init_data));
|
||||
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;
|
||||
}
|
||||
|
||||
if (ctrl_pdata->dba_ops.power_on)
|
||||
ctrl_pdata->dba_ops.power_on(ctrl_pdata->dba_data,
|
||||
true, 0);
|
||||
|
||||
ctrl_pdata->ds_registered = true;
|
||||
ctrl_pdata->hpd_state = true;
|
||||
mdss_dsi_send_cable_notification(ctrl_pdata, 1);
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
||||
int mdss_dsi_panel_init(struct device_node *node,
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata)
|
||||
struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
||||
int ndx)
|
||||
{
|
||||
int rc = 0;
|
||||
static const char *panel_name;
|
||||
|
@ -2606,5 +2755,7 @@ int mdss_dsi_panel_init(struct device_node *node,
|
|||
ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
|
||||
ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
|
||||
|
||||
mdss_dsi_ctrl_init_dba(ctrl_pdata, ndx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,4 +21,4 @@ config MSM_DBA_ADV7533
|
|||
---help---
|
||||
Support for ADV7533 DSI to HDMI display bridge driver. The driver
|
||||
controls the ADV7533 HW through the I2C interface and configures
|
||||
the DSi input and HDMI output video format.
|
||||
the DSI input and HDMI output video format.
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "msm_dba_internal.h"
|
||||
|
||||
#define ADV7533_REG_CHIP_REVISION (0x00)
|
||||
#define ADV7533_DSI_CEC_I2C_ADDR_REG (0xE1)
|
||||
#define ADV7533_RESET_DELAY (100)
|
||||
|
||||
#define PINCTRL_STATE_ACTIVE "pmx_adv7533_active"
|
||||
|
@ -45,7 +46,7 @@
|
|||
#define MAX_RW_TRIES (3)
|
||||
|
||||
enum adv7533_i2c_addr {
|
||||
ADV7533_MAIN = 0x39,
|
||||
ADV7533_MAIN = 0x3D,
|
||||
ADV7533_CEC_DSI = 0x3C,
|
||||
};
|
||||
|
||||
|
@ -60,6 +61,7 @@ struct adv7533_reg_cfg {
|
|||
u8 i2c_addr;
|
||||
u8 reg;
|
||||
u8 val;
|
||||
int sleep_in_ms;
|
||||
};
|
||||
|
||||
struct adv7533_platform_data {
|
||||
|
@ -89,98 +91,43 @@ struct adv7533_platform_data {
|
|||
};
|
||||
|
||||
static struct adv7533_reg_cfg adv7533_init_setup[] = {
|
||||
/* power down */
|
||||
{ADV7533_MAIN, 0x41, 0x50},
|
||||
/* HPD override */
|
||||
{ADV7533_MAIN, 0xD6, 0x48},
|
||||
{ADV7533_MAIN, 0xD6, 0x48, 5},
|
||||
/* power down */
|
||||
{ADV7533_MAIN, 0x41, 0x50, 5},
|
||||
/* color space */
|
||||
{ADV7533_MAIN, 0x16, 0x20},
|
||||
{ADV7533_MAIN, 0x16, 0x20, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_MAIN, 0x9A, 0xE0},
|
||||
{ADV7533_MAIN, 0x9A, 0xE0, 0},
|
||||
/* HDCP */
|
||||
{ADV7533_MAIN, 0xBA, 0x70},
|
||||
{ADV7533_MAIN, 0xBA, 0x70, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_MAIN, 0xDE, 0x82},
|
||||
{ADV7533_MAIN, 0xDE, 0x82, 0},
|
||||
/* V1P2 */
|
||||
{ADV7533_MAIN, 0xE4, 0x40},
|
||||
{ADV7533_MAIN, 0xE4, 0x40, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_MAIN, 0xE5, 0x80},
|
||||
{ADV7533_MAIN, 0xE5, 0x80, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_CEC_DSI, 0x15, 0xD0},
|
||||
{ADV7533_CEC_DSI, 0x15, 0xD0, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_CEC_DSI, 0x17, 0xD0},
|
||||
{ADV7533_CEC_DSI, 0x17, 0xD0, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_CEC_DSI, 0x24, 0x20},
|
||||
{ADV7533_CEC_DSI, 0x24, 0x20, 0},
|
||||
/* Fixed */
|
||||
{ADV7533_CEC_DSI, 0x57, 0x11},
|
||||
{ADV7533_CEC_DSI, 0x57, 0x11, 0},
|
||||
};
|
||||
|
||||
static struct adv7533_reg_cfg adv7533_video_setup[] = {
|
||||
/* power up */
|
||||
{ADV7533_MAIN, 0x41, 0x10},
|
||||
{ADV7533_MAIN, 0x41, 0x10, 0},
|
||||
/* hdmi enable */
|
||||
{ADV7533_CEC_DSI, 0x03, 0x89},
|
||||
{ADV7533_CEC_DSI, 0x03, 0x89, 0},
|
||||
/* hdmi mode, hdcp */
|
||||
{ADV7533_MAIN, 0xAF, 0x06},
|
||||
{ADV7533_MAIN, 0xAF, 0x06, 0},
|
||||
/* color depth */
|
||||
{ADV7533_MAIN, 0x4C, 0x04},
|
||||
{ADV7533_MAIN, 0x4C, 0x04, 0},
|
||||
/* down dither */
|
||||
{ADV7533_MAIN, 0x49, 0x02},
|
||||
};
|
||||
|
||||
static struct adv7533_reg_cfg tg_cfg_1080p[] = {
|
||||
/* 4 lanes */
|
||||
{ADV7533_CEC_DSI, 0x1C, 0x40},
|
||||
/* hsync and vsync active low */
|
||||
{ADV7533_MAIN, 0x17, 0x02},
|
||||
/* Control for Pixel Clock Divider */
|
||||
{ADV7533_CEC_DSI, 0x16, 0x00},
|
||||
/* Timing Generator Enable */
|
||||
{ADV7533_CEC_DSI, 0x27, 0xCB},
|
||||
/* h_width 0x898 2200*/
|
||||
{ADV7533_CEC_DSI, 0x28, 0x89},
|
||||
{ADV7533_CEC_DSI, 0x29, 0x80},
|
||||
/* hsync_width 0x2C 44*/
|
||||
{ADV7533_CEC_DSI, 0x2A, 0x02},
|
||||
{ADV7533_CEC_DSI, 0x2B, 0xC0},
|
||||
/* hfp 0x58 88 */
|
||||
{ADV7533_CEC_DSI, 0x2C, 0x05},
|
||||
{ADV7533_CEC_DSI, 0x2D, 0x80},
|
||||
/* hbp 0x94 148 */
|
||||
{ADV7533_CEC_DSI, 0x2E, 0x09},
|
||||
{ADV7533_CEC_DSI, 0x2F, 0x40},
|
||||
/* v_total 0x465 1125 */
|
||||
{ADV7533_CEC_DSI, 0x30, 0x46},
|
||||
{ADV7533_CEC_DSI, 0x31, 0x50},
|
||||
/* vsync_width 0x05 5*/
|
||||
{ADV7533_CEC_DSI, 0x32, 0x00},
|
||||
{ADV7533_CEC_DSI, 0x33, 0x50},
|
||||
/* vfp 0x04 4 */
|
||||
{ADV7533_CEC_DSI, 0x34, 0x00},
|
||||
{ADV7533_CEC_DSI, 0x35, 0x40},
|
||||
/* vbp 0x24 36 */
|
||||
{ADV7533_CEC_DSI, 0x36, 0x02},
|
||||
{ADV7533_CEC_DSI, 0x37, 0x40},
|
||||
/* Timing Generator Enable */
|
||||
{ADV7533_CEC_DSI, 0x27, 0xCB},
|
||||
{ADV7533_CEC_DSI, 0x27, 0x8B},
|
||||
{ADV7533_CEC_DSI, 0x27, 0xCB},
|
||||
/* Reset Internal Timing Generator */
|
||||
{ADV7533_MAIN, 0xAF, 0x16},
|
||||
/* HDMI Mode Select */
|
||||
{ADV7533_CEC_DSI, 0x78, 0x03},
|
||||
/* HDMI Output Enable */
|
||||
{ADV7533_MAIN, 0x40, 0x80},
|
||||
/* GC Packet Enable */
|
||||
{ADV7533_MAIN, 0x4C, 0x04},
|
||||
/* Colour Depth 24-bit per pixel */
|
||||
{ADV7533_MAIN, 0x49, 0x00},
|
||||
/* Down Dither Output 8-bit Colour Depth */
|
||||
{ADV7533_CEC_DSI, 0x05, 0xC8},
|
||||
/* ADI Required Write */
|
||||
{ADV7533_CEC_DSI, 0xBE, 0x3D},
|
||||
/* Test Pattern Disable (0x55[7] = 0) */
|
||||
{ADV7533_CEC_DSI, 0x55, 0x00},
|
||||
{ADV7533_MAIN, 0x49, 0x02, 0},
|
||||
};
|
||||
|
||||
static struct adv7533_reg_cfg I2S_cfg[] = {
|
||||
|
@ -287,9 +234,119 @@ w_err:
|
|||
if (ret != 0)
|
||||
pr_err("%s: Exiting with ret = %d after %d retries\n",
|
||||
__func__, ret, i);
|
||||
else
|
||||
pr_debug("[%s,%d] I2C write(0x%02x) [0x%02x]=0x%02x\n",
|
||||
__func__, __LINE__, addr, reg, val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adv7533_read_reg(struct msm_dba_device_info *dev, u32 reg, u32 *val)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 byte_val = 0, addr = 0;
|
||||
struct adv7533_platform_data *pdata = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("%s: dev is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdata = container_of(dev, struct adv7533_platform_data, dev_info);
|
||||
if (!pdata) {
|
||||
pr_err("%s: pdata is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = (reg & 0x0100)?(pdata->cec_dsi_i2c_addr):(pdata->main_i2c_addr);
|
||||
rc = adv7533_read_byte(addr, (reg & 0xff), &byte_val);
|
||||
if (rc) {
|
||||
pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n",
|
||||
__func__, reg, addr);
|
||||
} else {
|
||||
pr_debug("%s: read reg=0x%02x ok value=0x%02x @ addr=0x%02x\n",
|
||||
__func__, reg, byte_val, addr);
|
||||
*val = (u32)byte_val;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int adv7533_write_reg(struct msm_dba_device_info *dev, u32 reg, u32 val)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 addr = 0;
|
||||
struct adv7533_platform_data *pdata = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("%s: dev is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdata = container_of(dev, struct adv7533_platform_data, dev_info);
|
||||
if (!pdata) {
|
||||
pr_err("%s: pdata is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = (reg & 0x0100)?(pdata->cec_dsi_i2c_addr):(pdata->main_i2c_addr);
|
||||
rc = adv7533_write_byte(addr, (reg & 0xff), val);
|
||||
if (rc)
|
||||
pr_err("%s: write reg=0x%02x failed @ addr=0x%02x\n",
|
||||
__func__, reg, pdata->main_i2c_addr);
|
||||
else
|
||||
pr_debug("%s: write reg=0x%02x ok value=0x%02x @ addr=0x%02x\n",
|
||||
__func__, reg, val, pdata->main_i2c_addr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int adv7533_dump_debug_info(struct msm_dba_device_info *dev, u32 flags)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 byte_val = 0;
|
||||
u16 addr = 0;
|
||||
struct adv7533_platform_data *pdata = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("%s: dev is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdata = container_of(dev, struct adv7533_platform_data, dev_info);
|
||||
if (!pdata) {
|
||||
pr_err("%s: pdata is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* dump main addr*/
|
||||
pr_err("========Main I2C=0x%02x Start==========\n",
|
||||
pdata->main_i2c_addr);
|
||||
for (addr = 0; addr <= 0xFF; addr++) {
|
||||
rc = adv7533_read_byte(pdata->main_i2c_addr,
|
||||
(u8)addr, &byte_val);
|
||||
if (rc)
|
||||
pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n",
|
||||
__func__, addr, pdata->main_i2c_addr);
|
||||
else
|
||||
pr_err("0x%02x -> 0x%02X\n", addr, byte_val);
|
||||
}
|
||||
pr_err("========Main I2C=0x%02x End==========\n",
|
||||
pdata->main_i2c_addr);
|
||||
/* dump CEC addr*/
|
||||
pr_err("=======CEC I2C=0x%02x Start=========\n",
|
||||
pdata->cec_dsi_i2c_addr);
|
||||
for (addr = 0; addr <= 0xFF; addr++) {
|
||||
rc = adv7533_read_byte(pdata->cec_dsi_i2c_addr,
|
||||
(u8)addr, &byte_val);
|
||||
if (rc)
|
||||
pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n",
|
||||
__func__, addr, pdata->cec_dsi_i2c_addr);
|
||||
else
|
||||
pr_err("0x%02x -> 0x%02X\n", addr, byte_val);
|
||||
}
|
||||
pr_err("========CEC I2C=0x%02x End==========\n",
|
||||
pdata->cec_dsi_i2c_addr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int adv7533_write_regs(struct adv7533_platform_data *pdata,
|
||||
struct adv7533_reg_cfg *cfg, int size)
|
||||
{
|
||||
|
@ -323,6 +380,8 @@ static int adv7533_write_regs(struct adv7533_platform_data *pdata,
|
|||
cfg[i].val, cfg[i].reg);
|
||||
goto w_regs_fail;
|
||||
}
|
||||
if (cfg[i].sleep_in_ms)
|
||||
msleep(cfg[i].sleep_in_ms);
|
||||
}
|
||||
|
||||
w_regs_fail:
|
||||
|
@ -332,12 +391,12 @@ w_regs_fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int adv7533_read_device_rev(void)
|
||||
static int adv7533_read_device_rev(struct adv7533_platform_data *pdata)
|
||||
{
|
||||
u8 rev = 0;
|
||||
int ret;
|
||||
|
||||
ret = adv7533_read_byte(ADV7533_MAIN, ADV7533_REG_CHIP_REVISION,
|
||||
ret = adv7533_read_byte(pdata->main_i2c_addr, ADV7533_REG_CHIP_REVISION,
|
||||
&rev);
|
||||
|
||||
if (!ret)
|
||||
|
@ -348,13 +407,39 @@ static int adv7533_read_device_rev(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int adv7533_program_i2c_addr(struct adv7533_platform_data *pdata)
|
||||
{
|
||||
u8 i2c_8bits = pdata->cec_dsi_i2c_addr << 1;
|
||||
int ret = 0;
|
||||
|
||||
if (pdata->cec_dsi_i2c_addr != ADV7533_CEC_DSI) {
|
||||
ret = adv7533_write_byte(pdata->main_i2c_addr,
|
||||
ADV7533_DSI_CEC_I2C_ADDR_REG,
|
||||
i2c_8bits);
|
||||
|
||||
if (ret)
|
||||
pr_err("%s: write err CEC_ADDR[0x%02x] main_addr=0x%02x\n",
|
||||
__func__, ADV7533_DSI_CEC_I2C_ADDR_REG,
|
||||
pdata->main_i2c_addr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adv7533_parse_dt(struct device *dev,
|
||||
struct adv7533_platform_data *pdata)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 temp_val;
|
||||
u32 temp_val = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = of_property_read_u32(np, "instance_id", &temp_val);
|
||||
pr_debug("%s: DT property %s is %X\n", __func__, "instance_id",
|
||||
temp_val);
|
||||
if (ret)
|
||||
goto end;
|
||||
pdata->dev_info.instance_id = temp_val;
|
||||
|
||||
ret = of_property_read_u32(np, "adi,main-addr", &temp_val);
|
||||
pr_debug("%s: DT property %s is %X\n", __func__, "adi,main-addr",
|
||||
temp_val);
|
||||
|
@ -433,8 +518,8 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata,
|
|||
if (gpio_is_valid(pdata->irq_gpio)) {
|
||||
ret = gpio_request(pdata->irq_gpio, "adv7533_irq_gpio");
|
||||
if (ret) {
|
||||
pr_err("unable to request gpio [%d]\n",
|
||||
pdata->irq_gpio);
|
||||
pr_err("%d unable to request gpio [%d] ret=%d\n",
|
||||
__LINE__, pdata->irq_gpio, ret);
|
||||
goto err_none;
|
||||
}
|
||||
ret = gpio_direction_input(pdata->irq_gpio);
|
||||
|
@ -448,35 +533,16 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata,
|
|||
goto err_none;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->hpd_irq_gpio)) {
|
||||
ret = gpio_request(pdata->hpd_irq_gpio,
|
||||
"adv7533_hpd_irq_gpio");
|
||||
if (ret) {
|
||||
pr_err("unable to request gpio [%d]\n",
|
||||
pdata->hpd_irq_gpio);
|
||||
goto err_irq_gpio;
|
||||
}
|
||||
ret = gpio_direction_input(pdata->hpd_irq_gpio);
|
||||
if (ret) {
|
||||
pr_err("unable to set dir for gpio[%d]\n",
|
||||
pdata->hpd_irq_gpio);
|
||||
goto err_hpd_irq_gpio;
|
||||
}
|
||||
} else {
|
||||
pr_err("hpd irq gpio not provided\n");
|
||||
goto err_irq_gpio;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->switch_gpio)) {
|
||||
ret = gpio_request(pdata->switch_gpio,
|
||||
"adv7533_switch_gpio");
|
||||
if (ret) {
|
||||
pr_err("unable to request gpio [%d]\n",
|
||||
pdata->switch_gpio);
|
||||
pr_err("%d unable to request gpio [%d] ret=%d\n",
|
||||
__LINE__, pdata->irq_gpio, ret);
|
||||
goto err_hpd_irq_gpio;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(pdata->switch_gpio, 1);
|
||||
ret = gpio_direction_output(pdata->switch_gpio, 0);
|
||||
if (ret) {
|
||||
pr_err("unable to set dir for gpio [%d]\n",
|
||||
pdata->switch_gpio);
|
||||
|
@ -496,7 +562,7 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata,
|
|||
if (gpio_is_valid(pdata->switch_gpio))
|
||||
gpio_free(pdata->switch_gpio);
|
||||
|
||||
return 0;
|
||||
goto err_none;
|
||||
}
|
||||
|
||||
err_switch_gpio:
|
||||
|
@ -512,32 +578,8 @@ err_none:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void adv7533_get_cmdline_config(void)
|
||||
{
|
||||
int len = 0;
|
||||
char *t;
|
||||
|
||||
len = strlen(mdss_mdp_panel);
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
t = strnstr(mdss_mdp_panel, "hdmi", MDSS_MAX_PANEL_LEN);
|
||||
if (t)
|
||||
pdata->adv_output = true;
|
||||
else
|
||||
pdata->adv_output = false;
|
||||
|
||||
t = strnstr(mdss_mdp_panel, "720", MDSS_MAX_PANEL_LEN);
|
||||
if (t)
|
||||
pdata->video_mode = ADV7533_VIDEO_720P;
|
||||
|
||||
t = strnstr(mdss_mdp_panel, "1080", MDSS_MAX_PANEL_LEN);
|
||||
if (t)
|
||||
pdata->video_mode = ADV7533_VIDEO_1080P;
|
||||
}
|
||||
|
||||
u32 adv7533_read_edid(u32 size, char *edid_buf)
|
||||
u32 adv7533_read_edid(struct adv7533_platform_data *pdata,
|
||||
u32 size, char *edid_buf)
|
||||
{
|
||||
u32 ret = 0, ndx;
|
||||
u8 edid_addr;
|
||||
|
@ -548,7 +590,7 @@ u32 adv7533_read_edid(u32 size, char *edid_buf)
|
|||
|
||||
pr_debug("%s: size %d\n", __func__, size);
|
||||
|
||||
ret = adv7533_read(ADV7533_MAIN, 0x43, &edid_addr, 1);
|
||||
ret = adv7533_read(pdata->main_i2c_addr, 0x43, &edid_addr, 1);
|
||||
if (ret) {
|
||||
pr_err("%s: Error reading edid addr\n", __func__);
|
||||
goto end;
|
||||
|
@ -594,8 +636,8 @@ static void adv7533_intr_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
/* READ Interrupt registers */
|
||||
adv7533_read_byte(ADV7533_MAIN, 0x96, &int_status);
|
||||
adv7533_read_byte(ADV7533_MAIN, 0x42, &int_state);
|
||||
adv7533_read_byte(pdata->main_i2c_addr, 0x96, &int_status);
|
||||
adv7533_read_byte(pdata->main_i2c_addr, 0x42, &int_state);
|
||||
|
||||
if (int_status & BIT(6)) {
|
||||
if (int_state & BIT(5)) {
|
||||
|
@ -623,7 +665,7 @@ static void adv7533_intr_work(struct work_struct *work)
|
|||
if (int_status & BIT(2)) {
|
||||
pr_info("%s: EDID READY\n", __func__);
|
||||
|
||||
ret = adv7533_read_edid(sizeof(pdata->edid_buf),
|
||||
ret = adv7533_read_edid(pdata, sizeof(pdata->edid_buf),
|
||||
pdata->edid_buf);
|
||||
if (ret)
|
||||
pr_err("%s: edid read failed\n", __func__);
|
||||
|
@ -714,12 +756,86 @@ static int adv7533_power_on(void *client, bool on, u32 flags)
|
|||
goto end;
|
||||
}
|
||||
|
||||
queue_delayed_work(pdata->workq, &pdata->adv7533_intr_work_id, HZ/2);
|
||||
if (pdata->workq)
|
||||
queue_delayed_work(pdata->workq, &pdata->adv7533_intr_work_id,
|
||||
HZ/2);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void adv7533_video_timing_setup(struct adv7533_platform_data *pdata,
|
||||
struct msm_dba_video_cfg *cfg)
|
||||
{
|
||||
u32 h_total, hpw, hfp, hbp;
|
||||
u32 v_total, vpw, vfp, vbp;
|
||||
u32 num_lanes;
|
||||
u8 addr = 0;
|
||||
|
||||
if (!pdata || !cfg) {
|
||||
pr_err("%s: invalid input\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
h_total = cfg->h_active + cfg->h_front_porch +
|
||||
cfg->h_pulse_width + cfg->h_back_porch;
|
||||
v_total = cfg->v_active + cfg->v_front_porch +
|
||||
cfg->v_pulse_width + cfg->v_back_porch;
|
||||
|
||||
hpw = cfg->h_pulse_width;
|
||||
hfp = cfg->h_front_porch;
|
||||
hbp = cfg->h_back_porch;
|
||||
|
||||
vpw = cfg->v_pulse_width;
|
||||
vfp = cfg->v_front_porch;
|
||||
vbp = cfg->v_back_porch;
|
||||
addr = pdata->cec_dsi_i2c_addr;
|
||||
num_lanes = cfg->num_of_input_lanes;
|
||||
|
||||
pr_debug("h_total 0x%x, h_active 0x%x, hfp 0x%d, hpw 0x%x, hbp 0x%x\n",
|
||||
h_total, cfg->h_active, cfg->h_front_porch,
|
||||
cfg->h_pulse_width, cfg->h_back_porch);
|
||||
|
||||
pr_debug("v_total 0x%x, v_active 0x%x, vfp 0x%x, vpw 0x%x, vbp 0x%x\n",
|
||||
v_total, cfg->v_active, cfg->v_front_porch,
|
||||
cfg->v_pulse_width, cfg->v_back_porch);
|
||||
|
||||
/* lane setup */
|
||||
adv7533_write_byte(addr, 0x1C, ((num_lanes & 0xF) << 4));
|
||||
|
||||
/* h_width */
|
||||
adv7533_write_byte(addr, 0x28, ((h_total & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x29, ((h_total & 0xF) << 4));
|
||||
|
||||
/* hsync_width */
|
||||
adv7533_write_byte(addr, 0x2A, ((hpw & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x2B, ((hpw & 0xF) << 4));
|
||||
|
||||
/* hfp */
|
||||
adv7533_write_byte(addr, 0x2C, ((hfp & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x2D, ((hfp & 0xF) << 4));
|
||||
|
||||
/* hbp */
|
||||
adv7533_write_byte(addr, 0x2E, ((hbp & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x2F, ((hbp & 0xF) << 4));
|
||||
|
||||
/* v_total */
|
||||
adv7533_write_byte(addr, 0x30, ((v_total & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x31, ((v_total & 0xF) << 4));
|
||||
|
||||
/* vsync_width */
|
||||
adv7533_write_byte(addr, 0x32, ((vpw & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x33, ((vpw & 0xF) << 4));
|
||||
|
||||
/* vfp */
|
||||
adv7533_write_byte(addr, 0x34, ((vfp & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x35, ((vfp & 0xF) << 4));
|
||||
|
||||
/* vbp */
|
||||
adv7533_write_byte(addr, 0x36, ((vbp & 0xFF0) >> 4));
|
||||
adv7533_write_byte(addr, 0x37, ((vbp & 0xF) << 4));
|
||||
}
|
||||
|
||||
static int adv7533_video_on(void *client, bool on,
|
||||
struct msm_dba_video_cfg *cfg, u32 flags)
|
||||
{
|
||||
|
@ -732,12 +848,7 @@ static int adv7533_video_on(void *client, bool on,
|
|||
goto end;
|
||||
}
|
||||
|
||||
ret = adv7533_write_regs(pdata, tg_cfg_1080p,
|
||||
ARRAY_SIZE(tg_cfg_1080p));
|
||||
if (ret) {
|
||||
pr_err("%s: err config 1080p %d\n", __func__, ret);
|
||||
goto end;
|
||||
}
|
||||
adv7533_video_timing_setup(pdata, cfg);
|
||||
|
||||
ret = adv7533_write_regs(pdata, adv7533_video_setup,
|
||||
ARRAY_SIZE(adv7533_video_setup));
|
||||
|
@ -812,11 +923,13 @@ static int adv7533_register_dba(struct adv7533_platform_data *pdata)
|
|||
client_ops->video_on = adv7533_video_on;
|
||||
client_ops->get_edid_size = adv7533_get_edid_size;
|
||||
client_ops->get_raw_edid = adv7533_get_raw_edid;
|
||||
pdata->dev_info.dev_ops.read_reg = adv7533_read_reg;
|
||||
pdata->dev_info.dev_ops.write_reg = adv7533_write_reg;
|
||||
pdata->dev_info.dev_ops.dump_debug_info = adv7533_dump_debug_info;
|
||||
|
||||
strlcpy(pdata->dev_info.chip_name, "adv7533",
|
||||
sizeof(pdata->dev_info.chip_name));
|
||||
|
||||
pdata->dev_info.instance_id = 0;
|
||||
pdata->dev_info.reg_fxn = adv7533_reg_fxn;
|
||||
|
||||
mutex_init(&pdata->dev_info.dev_mutex);
|
||||
|
@ -826,13 +939,20 @@ static int adv7533_register_dba(struct adv7533_platform_data *pdata)
|
|||
return msm_dba_add_probed_device(&pdata->dev_info);
|
||||
}
|
||||
|
||||
static void adv7533_unregister_dba(struct adv7533_platform_data *pdata)
|
||||
{
|
||||
if (!pdata)
|
||||
return;
|
||||
|
||||
msm_dba_remove_probed_device(&pdata->dev_info);
|
||||
}
|
||||
|
||||
static int adv7533_probe(struct i2c_client *client_,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
client = client_;
|
||||
|
||||
client = client_;
|
||||
if (client->dev.of_node) {
|
||||
pdata = devm_kzalloc(&client->dev,
|
||||
sizeof(struct adv7533_platform_data), GFP_KERNEL);
|
||||
|
@ -842,42 +962,51 @@ static int adv7533_probe(struct i2c_client *client_,
|
|||
ret = adv7533_parse_dt(&client->dev, pdata);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to parse DT\n", __func__);
|
||||
goto p_err;
|
||||
goto err_dt_parse;
|
||||
}
|
||||
}
|
||||
|
||||
ret = adv7533_read_device_rev();
|
||||
ret = adv7533_read_device_rev(pdata);
|
||||
if (ret != 0) {
|
||||
pr_err("%s: Failed to read revision\n", __func__);
|
||||
goto p_err;
|
||||
goto err_dt_parse;
|
||||
}
|
||||
|
||||
ret = adv7533_program_i2c_addr(pdata);
|
||||
if (ret != 0) {
|
||||
pr_err("%s: Failed to program i2c addr\n", __func__);
|
||||
goto err_dt_parse;
|
||||
}
|
||||
|
||||
ret = adv7533_register_dba(pdata);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pr_err("%s: Error registering with DBA %d\n",
|
||||
__func__, ret);
|
||||
goto err_dba_reg;
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(pdata->ts_pinctrl,
|
||||
pdata->pinctrl_state_active);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to select %s pinstate %d\n",
|
||||
__func__, PINCTRL_STATE_ACTIVE, ret);
|
||||
goto err_dba_reg;
|
||||
}
|
||||
|
||||
pdata->adv_output = true;
|
||||
adv7533_get_cmdline_config();
|
||||
|
||||
if (!(pdata->disable_gpios)) {
|
||||
ret = adv7533_gpio_configure(pdata, true);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to configure GPIOs\n", __func__);
|
||||
goto p_err;
|
||||
goto err_gpio_cfg;
|
||||
}
|
||||
|
||||
if (pdata->adv_output) {
|
||||
gpio_set_value(pdata->switch_gpio, 0);
|
||||
} else {
|
||||
gpio_set_value(pdata->switch_gpio, 1);
|
||||
goto p_err;
|
||||
goto err_gpio_cfg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -888,7 +1017,7 @@ static int adv7533_probe(struct i2c_client *client_,
|
|||
if (ret) {
|
||||
pr_err("%s: Failed to enable ADV7533 interrupt\n",
|
||||
__func__);
|
||||
goto p_err;
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
if (pdata->audio) {
|
||||
|
@ -896,14 +1025,22 @@ static int adv7533_probe(struct i2c_client *client_,
|
|||
if (ret != 0) {
|
||||
pr_err("%s: I2S configuration fail = %d!\n",
|
||||
__func__, ret);
|
||||
goto p_err;
|
||||
goto err_dba_helper;
|
||||
}
|
||||
}
|
||||
|
||||
dev_set_drvdata(&client->dev, &pdata->dev_info);
|
||||
ret = msm_dba_helper_sysfs_init(&client->dev);
|
||||
if (ret) {
|
||||
pr_err("%s: sysfs init failed\n", __func__);
|
||||
goto err_dba_helper;
|
||||
}
|
||||
|
||||
pdata->workq = create_workqueue("adv7533_workq");
|
||||
if (!pdata->workq) {
|
||||
pr_err("%s: workqueue creation failed.\n", __func__);
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
goto err_workqueue;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&pdata->adv7533_intr_work_id, adv7533_intr_work);
|
||||
|
@ -913,8 +1050,17 @@ static int adv7533_probe(struct i2c_client *client_,
|
|||
|
||||
return 0;
|
||||
|
||||
p_err:
|
||||
err_workqueue:
|
||||
msm_dba_helper_sysfs_remove(&client->dev);
|
||||
err_dba_helper:
|
||||
disable_irq(pdata->irq);
|
||||
free_irq(pdata->irq, pdata);
|
||||
err_irq:
|
||||
adv7533_gpio_configure(pdata, false);
|
||||
err_gpio_cfg:
|
||||
adv7533_unregister_dba(pdata);
|
||||
err_dba_reg:
|
||||
err_dt_parse:
|
||||
devm_kfree(&client->dev, pdata);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
static inline struct msm_dba_device_info *to_dba_dev(struct device *dev)
|
||||
{
|
||||
if (!dev) {
|
||||
pr_err("%s: dev is NULL\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
return dev_get_drvdata(dev);
|
||||
}
|
||||
|
||||
|
@ -35,6 +39,11 @@ static ssize_t device_name_rda_attr(struct device *dev,
|
|||
{
|
||||
struct msm_dba_device_info *device = to_dba_dev(dev);
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s:%d\n", device->chip_name,
|
||||
device->instance_id);
|
||||
}
|
||||
|
@ -48,6 +57,11 @@ static ssize_t client_list_rda_attr(struct device *dev,
|
|||
struct list_head *pos = NULL;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&device->dev_mutex);
|
||||
|
||||
list_for_each(pos, &device->client_list) {
|
||||
|
@ -70,6 +84,11 @@ static ssize_t power_status_rda_attr(struct device *dev,
|
|||
struct list_head *pos = NULL;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&device->dev_mutex);
|
||||
bytes = snprintf(buf, PAGE_SIZE, "power_status:%d\n",
|
||||
device->power_status);
|
||||
|
@ -94,6 +113,11 @@ static ssize_t video_status_rda_attr(struct device *dev,
|
|||
struct list_head *pos = NULL;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&device->dev_mutex);
|
||||
bytes = snprintf(buf, PAGE_SIZE, "video_status:%d\n",
|
||||
device->video_status);
|
||||
|
@ -118,6 +142,11 @@ static ssize_t audio_status_rda_attr(struct device *dev,
|
|||
struct list_head *pos = NULL;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&device->dev_mutex);
|
||||
bytes = snprintf(buf, PAGE_SIZE, "audio_status:%d\n",
|
||||
device->audio_status);
|
||||
|
@ -146,6 +175,11 @@ static ssize_t write_reg_wta_attr(struct device *dev,
|
|||
int rc = 0;
|
||||
int len;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = strlen(buf);
|
||||
strlcpy(str, buf, 20);
|
||||
if (len < 20)
|
||||
|
@ -195,6 +229,11 @@ static ssize_t read_reg_rda_attr(struct device *dev,
|
|||
struct msm_dba_device_info *device = to_dba_dev(dev);
|
||||
ssize_t bytes;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&device->dev_mutex);
|
||||
|
||||
bytes = snprintf(buf, PAGE_SIZE, "0x%x\n", device->register_val);
|
||||
|
@ -214,6 +253,11 @@ static ssize_t read_reg_wta_attr(struct device *dev,
|
|||
int rc = 0;
|
||||
u32 val = 0;
|
||||
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return count;
|
||||
}
|
||||
|
||||
rc = kstrtol(buf, 0, ®);
|
||||
if (rc) {
|
||||
pr_err("%s: kstrol error %d\n", __func__, rc);
|
||||
|
@ -249,9 +293,18 @@ static ssize_t dump_info_wta_attr(struct device *dev,
|
|||
struct msm_dba_device_info *device = to_dba_dev(dev);
|
||||
int rc;
|
||||
|
||||
rc = device->dev_ops.dump_debug_info(device, 0x00);
|
||||
if (rc)
|
||||
pr_err("%s: failed to dump debug data\n", __func__);
|
||||
if (!device) {
|
||||
pr_err("%s: device is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device->dev_ops.dump_debug_info) {
|
||||
rc = device->dev_ops.dump_debug_info(device, 0x00);
|
||||
if (rc)
|
||||
pr_err("%s: failed to dump debug data\n", __func__);
|
||||
} else {
|
||||
pr_err("%s: not supported\n", __func__);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -297,3 +350,13 @@ int msm_dba_helper_sysfs_init(struct device *dev)
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void msm_dba_helper_sysfs_remove(struct device *dev)
|
||||
{
|
||||
if (!dev) {
|
||||
pr_err("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sysfs_remove_group(&dev->kobj, &msm_dba_sysfs_attr_grp);
|
||||
}
|
||||
|
|
|
@ -53,9 +53,8 @@ int msm_dba_add_probed_device(struct msm_dba_device_info *dev)
|
|||
node->dev = dev;
|
||||
list_add(&node->list, &device_list);
|
||||
|
||||
pr_debug("%s: Added new device (%s, %d)", __func__, dev->chip_name,
|
||||
pr_debug("%s: Added new device (%s, %d)\n", __func__, dev->chip_name,
|
||||
dev->instance_id);
|
||||
|
||||
mutex_unlock(&init_mutex);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -305,6 +305,13 @@ int msm_dba_register_hdcp_monitor(struct msm_dba_device_info *dev, bool enable);
|
|||
*/
|
||||
int msm_dba_helper_sysfs_init(struct device *dev);
|
||||
|
||||
/**
|
||||
* msm_dba_helper_sysfs_remove() - remove sysfs attributes
|
||||
* @dev: pointer to struct device structure.
|
||||
*
|
||||
*/
|
||||
void msm_dba_helper_sysfs_remove(struct device *dev);
|
||||
|
||||
/**
|
||||
* msm_dba_helper_force_reset() - force reset bridge chip
|
||||
* @client: client handle
|
||||
|
|
Loading…
Add table
Reference in a new issue