diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 6e9f437c852b5..ac45dae3f0433 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -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) @@ -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; } @@ -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); @@ -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", @@ -5810,113 +5901,15 @@ 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; @@ -5924,25 +5917,11 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) 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) {