Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 102 additions & 123 deletions drivers/gpu/drm/panel/panel-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,90 @@ static struct panel_desc *panel_dpi_probe(struct device *dev)
return desc;
}

static struct panel_desc *panel_dsi_probe(struct device *dev)
{
const struct device_node *np = dev->of_node;
struct panel_desc_dsi *desc_dsi;
struct panel_desc *desc;
const char *dsi_color_format;
const char *dsi_mode_flags;
struct property *prop;
int dsi_lanes;

desc = panel_dpi_probe(dev);
if (IS_ERR(desc)) {
pr_err("Failed panel_dpi_probe\n");
return desc;
}

desc->connector_type = DRM_MODE_CONNECTOR_DSI;

desc_dsi = devm_kzalloc(dev, sizeof(*desc_dsi), GFP_KERNEL);
if (!desc_dsi)
return ERR_PTR(-ENOMEM);

desc_dsi->desc = *desc;
devm_kfree(dev, desc);

desc = &desc_dsi->desc;

dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4);

if (dsi_lanes < 0) {
dev_err(dev, "%pOF: no or too many data-lanes defined", np);
return ERR_PTR(dsi_lanes);
}

desc_dsi->lanes = dsi_lanes;

of_property_read_string(np, "dsi-color-format", &dsi_color_format);
if (!strcmp(dsi_color_format, "RGB888")) {
desc_dsi->format = MIPI_DSI_FMT_RGB888;
desc_dsi->desc.bpc = 8;
} else if (!strcmp(dsi_color_format, "RGB565")) {
desc_dsi->format = MIPI_DSI_FMT_RGB565;
desc_dsi->desc.bpc = 6;
} else if (!strcmp(dsi_color_format, "RGB666")) {
desc_dsi->format = MIPI_DSI_FMT_RGB666;
desc_dsi->desc.bpc = 6;
} else if (!strcmp(dsi_color_format, "RGB666_PACKED")) {
desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED;
desc_dsi->desc.bpc = 6;
} else {
dev_err(dev, "%pOF: no valid dsi-color-format defined", np);
return ERR_PTR(-EINVAL);
}

of_property_for_each_string(np, "mode", prop, dsi_mode_flags) {
if (!strcmp(dsi_mode_flags, "MODE_VIDEO"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA;
else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET"))
desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET;
else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS"))
desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
else if (!strcmp(dsi_mode_flags, "MODE_LPM"))
desc_dsi->flags |= MIPI_DSI_MODE_LPM;
else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED"))
desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED;
}

return &desc_dsi->desc;
}

#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \
(to_check->field.typ >= bounds->field.min && \
to_check->field.typ <= bounds->field.max)
Expand Down Expand Up @@ -568,8 +652,17 @@ static const struct panel_desc *panel_simple_get_desc(struct device *dev)
const struct panel_desc_dsi *dsi_desc;

dsi_desc = of_device_get_match_data(dev);
if (!dsi_desc)
return ERR_PTR(-ENODEV);
if (!dsi_desc) {
/*
* panel-dsi probes without a descriptor and
* panel_dsi_probe() will initialize one for us
* based on the device tree.
*/
if (of_device_is_compatible(dev->of_node, "panel-dsi"))
return panel_dsi_probe(dev);
else
return ERR_PTR(-ENODEV);
}

return &dsi_desc->desc;
}
Expand Down Expand Up @@ -689,7 +782,8 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
return ERR_PTR(-EPROBE_DEFER);
}

if (!of_device_is_compatible(dev->of_node, "panel-dpi") &&
if (!(of_device_is_compatible(dev->of_node, "panel-dpi") ||
of_device_is_compatible(dev->of_node, "panel-dsi")) &&
!of_get_display_timing(dev->of_node, "panel-timing", &dt))
panel_simple_parse_panel_timing_node(dev, panel, &dt);

Expand Down Expand Up @@ -5782,9 +5876,6 @@ static const struct panel_desc_dsi osd101t2045_53ts = {
.lanes = 4,
};

// for panels using generic panel-dsi binding
static struct panel_desc_dsi panel_dsi;

static const struct of_device_id dsi_of_match[] = {
{
.compatible = "auo,b080uan01",
Expand All @@ -5810,139 +5901,27 @@ static const struct of_device_id dsi_of_match[] = {
}, {
/* Must be the last entry */
.compatible = "panel-dsi",
.data = &panel_dsi,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, dsi_of_match);


/* Checks for DSI panel definition in device-tree, analog to panel_dpi */
static int panel_dsi_dt_probe(struct device *dev,
struct panel_desc_dsi *desc_dsi)
{
struct panel_desc *desc;
struct display_timing *timing;
const struct device_node *np;
const char *dsi_color_format;
const char *dsi_mode_flags;
struct property *prop;
int dsi_lanes, ret;

np = dev->of_node;

desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;

timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
if (!timing)
return -ENOMEM;

ret = of_get_display_timing(np, "panel-timing", timing);
if (ret < 0) {
dev_err(dev, "%pOF: no panel-timing node found for \"panel-dsi\" binding\n",
np);
return ret;
}

desc->timings = timing;
desc->num_timings = 1;

of_property_read_u32(np, "width-mm", &desc->size.width);
of_property_read_u32(np, "height-mm", &desc->size.height);

dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4);

if (dsi_lanes < 0) {
dev_err(dev, "%pOF: no or too many data-lanes defined", np);
return dsi_lanes;
}

desc_dsi->lanes = dsi_lanes;

of_property_read_string(np, "dsi-color-format", &dsi_color_format);
if (!strcmp(dsi_color_format, "RGB888")) {
desc_dsi->format = MIPI_DSI_FMT_RGB888;
desc->bpc = 8;
} else if (!strcmp(dsi_color_format, "RGB565")) {
desc_dsi->format = MIPI_DSI_FMT_RGB565;
desc->bpc = 6;
} else if (!strcmp(dsi_color_format, "RGB666")) {
desc_dsi->format = MIPI_DSI_FMT_RGB666;
desc->bpc = 6;
} else if (!strcmp(dsi_color_format, "RGB666_PACKED")) {
desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED;
desc->bpc = 6;
} else {
dev_err(dev, "%pOF: no valid dsi-color-format defined", np);
return -EINVAL;
}


of_property_for_each_string(np, "mode", prop, dsi_mode_flags) {
if (!strcmp(dsi_mode_flags, "MODE_VIDEO"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP;
else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA"))
desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA;
else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET"))
desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET;
else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS"))
desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
else if (!strcmp(dsi_mode_flags, "MODE_LPM"))
desc_dsi->flags |= MIPI_DSI_MODE_LPM;
else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED"))
desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED;
}

desc->connector_type = DRM_MODE_CONNECTOR_DSI;
desc_dsi->desc = *desc;

return 0;
}

static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
{
const struct panel_desc_dsi *desc;
const struct panel_desc_dsi *dsi_desc;
struct panel_simple *panel;
int err;

panel = panel_simple_probe(&dsi->dev);
if (IS_ERR(panel))
return PTR_ERR(panel);

desc = container_of(panel->desc, struct panel_desc_dsi, desc);

if (desc == &panel_dsi) {
/* Handle the generic panel-dsi binding */
struct panel_desc_dsi *dt_desc;
dt_desc = devm_kzalloc(&dsi->dev, sizeof(*dt_desc), GFP_KERNEL);
if (!dt_desc)
return -ENOMEM;

err = panel_dsi_dt_probe(&dsi->dev, dt_desc);
if (err < 0)
return err;

desc = dt_desc;
}
dsi_desc = container_of(panel->desc, struct panel_desc_dsi, desc);

dsi->mode_flags = desc->flags;
dsi->format = desc->format;
dsi->lanes = desc->lanes;
dsi->mode_flags = dsi_desc->flags;
dsi->format = dsi_desc->format;
dsi->lanes = dsi_desc->lanes;

err = mipi_dsi_attach(dsi);
if (err) {
Expand Down
Loading