static int imx_pd_connector_get_modes(struct drm_connector *connector) { struct imx_parallel_display *imxpd = con_to_imxpd(connector); struct device_node *np = imxpd->dev->of_node; int num_modes = 0; if (imxpd->edid) { drm_mode_connector_update_edid_property(connector, imxpd->edid); num_modes = drm_add_edid_modes(connector, imxpd->edid); } if (imxpd->mode_valid) { struct drm_display_mode *mode = drm_mode_create(connector->dev); drm_mode_copy(mode, &imxpd->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, drm_mode_probed_add(connector, mode); num_modes++; } if (np) { struct drm_display_mode *mode = drm_mode_create(connector->dev); of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE); drm_mode_copy(mode, &imxpd->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, drm_mode_probed_add(connector, mode); num_modes++; } return num_modes; }
static int imx_pd_connector_get_modes(struct drm_connector *connector) { struct imx_parallel_display *imxpd = con_to_imxpd(connector); struct device_node *np = imxpd->dev->of_node; int num_modes = 0; if (imxpd->panel && imxpd->panel->funcs && imxpd->panel->funcs->get_modes) { struct drm_display_info *di = &connector->display_info; num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); if (!imxpd->bus_format && di->num_bus_formats) imxpd->bus_format = di->bus_formats[0]; if (num_modes > 0) return num_modes; } if (imxpd->edid) { drm_mode_connector_update_edid_property(connector, imxpd->edid); num_modes = drm_add_edid_modes(connector, imxpd->edid); } if (imxpd->mode_valid) { struct drm_display_mode *mode = drm_mode_create(connector->dev); if (!mode) return -EINVAL; drm_mode_copy(mode, &imxpd->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, drm_mode_probed_add(connector, mode); num_modes++; } if (np) { struct drm_display_mode *mode = drm_mode_create(connector->dev); if (!mode) return -EINVAL; of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE); drm_mode_copy(mode, &imxpd->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, drm_mode_probed_add(connector, mode); num_modes++; } return num_modes; }
static int imx_ldb_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; const struct of_device_id *of_id = of_match_device(imx_ldb_dt_ids, dev); struct device_node *child; const u8 *edidp; struct imx_ldb *imx_ldb; int datawidth; int mapping; int dual; int ret; int i; imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL); if (!imx_ldb) return -ENOMEM; imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); if (IS_ERR(imx_ldb->regmap)) { dev_err(dev, "failed to get parent regmap\n"); return PTR_ERR(imx_ldb->regmap); } imx_ldb->dev = dev; if (of_id) imx_ldb->lvds_mux = of_id->data; dual = of_property_read_bool(np, "fsl,dual-channel"); if (dual) imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; /* * There are three different possible clock mux configurations: * i.MX53: ipu1_di0_sel, ipu1_di1_sel * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel * Map them all to di0_sel...di3_sel. */ for (i = 0; i < 4; i++) { char clkname[16]; sprintf(clkname, "di%d_sel", i); imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname); if (IS_ERR(imx_ldb->clk_sel[i])) { ret = PTR_ERR(imx_ldb->clk_sel[i]); imx_ldb->clk_sel[i] = NULL; break; } } if (i == 0) return ret; for_each_child_of_node(np, child) { struct imx_ldb_channel *channel; struct device_node *panel_node; ret = of_property_read_u32(child, "reg", &i); if (ret || i < 0 || i > 1) return -EINVAL; if (dual && i > 0) { dev_warn(dev, "dual-channel mode, ignoring second output\n"); continue; } if (!of_device_is_available(child)) continue; channel = &imx_ldb->channel[i]; channel->ldb = imx_ldb; channel->chno = i; channel->child = child; edidp = of_get_property(child, "edid", &channel->edid_len); if (edidp) { channel->edid = kmemdup(edidp, channel->edid_len, GFP_KERNEL); } else { ret = of_get_drm_display_mode(child, &channel->mode, 0); if (!ret) channel->mode_valid = 1; } ret = of_property_read_u32(child, "fsl,data-width", &datawidth); if (ret) datawidth = 0; else if (datawidth != 18 && datawidth != 24) return -EINVAL; mapping = of_get_data_mapping(child); switch (mapping) { case LVDS_BIT_MAP_SPWG: if (datawidth == 24) { if (i == 0 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; if (i == 1 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; } break; case LVDS_BIT_MAP_JEIDA: if (datawidth == 18) { dev_err(dev, "JEIDA standard only supported in 24 bit\n"); return -EINVAL; } if (i == 0 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | LDB_BIT_MAP_CH0_JEIDA; if (i == 1 || dual) imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA; break; default: dev_err(dev, "data mapping not specified or invalid\n"); return -EINVAL; } panel_node = of_parse_phandle(child, "fsl,panel", 0); if (panel_node) channel->panel = of_drm_find_panel(panel_node); ret = imx_ldb_register(drm, channel); if (ret) return ret; } dev_set_drvdata(dev, imx_ldb); return 0; }