static int panel_dpi_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct omap_dss_device *in; int r; struct display_timing timing; struct videomode vm; struct gpio_desc *gpio; gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(gpio)) return PTR_ERR(gpio); ddata->enable_gpio = gpio; /* * Many different panels are supported by this driver and there are * probably very different needs for their reset pins in regards to * timing and order relative to the enable gpio. So for now it's just * ensured that the reset line isn't active. */ gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(gpio)) return PTR_ERR(gpio); ddata->vcc_supply = devm_regulator_get(&pdev->dev, "vcc"); if (IS_ERR(ddata->vcc_supply)) return PTR_ERR(ddata->vcc_supply); ddata->backlight_gpio = -ENOENT; r = of_get_display_timing(node, "panel-timing", &timing); if (r) { dev_err(&pdev->dev, "failed to get video timing\n"); return r; } videomode_from_timing(&timing, &vm); videomode_to_omap_video_timings(&vm, &ddata->videomode); in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { dev_err(&pdev->dev, "failed to find video source\n"); return PTR_ERR(in); } ddata->in = in; return 0; }
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, struct rcar_du_encoder *renc, /* TODO const */ struct device_node *np) { struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc); struct rcar_du_lvds_connector *lvdscon; struct drm_connector *connector; struct display_timing timing; int ret; lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL); if (lvdscon == NULL) return -ENOMEM; ret = of_get_display_timing(np, "panel-timing", &timing); if (ret < 0) return ret; videomode_from_timing(&timing, &lvdscon->panel.mode); of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm); of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm); connector = &lvdscon->connector.connector; connector->display_info.width_mm = lvdscon->panel.width_mm; connector->display_info.height_mm = lvdscon->panel.height_mm; ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, DRM_MODE_CONNECTOR_LVDS); if (ret < 0) return ret; drm_connector_helper_add(connector, &connector_helper_funcs); ret = drm_connector_register(connector); if (ret < 0) return ret; drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); drm_object_property_set_value(&connector->base, rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF); ret = drm_mode_connector_attach_encoder(connector, encoder); if (ret < 0) return ret; connector->encoder = encoder; lvdscon->connector.encoder = renc; return 0; }
static int panel_dpi_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct omap_dss_device *in; int r; struct display_timing timing; struct videomode vm; struct gpio_desc *gpio; gpio = devm_gpiod_get(&pdev->dev, "enable"); if (IS_ERR(gpio)) { if (PTR_ERR(gpio) != -ENOENT) return PTR_ERR(gpio); else gpio = NULL; } else { gpiod_direction_output(gpio, 0); } ddata->enable_gpio = gpio; ddata->backlight_gpio = -ENOENT; r = of_get_display_timing(node, "panel-timing", &timing); if (r) { dev_err(&pdev->dev, "failed to get video timing\n"); return r; } videomode_from_timing(&timing, &vm); videomode_to_omap_video_timings(&vm, &ddata->videomode); in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { dev_err(&pdev->dev, "failed to find video source\n"); return PTR_ERR(in); } ddata->in = in; return 0; }
/** * of_get_display_timings - parse all display_timing entries from a device_node * @np: device_node with the subnodes **/ struct display_timings *of_get_display_timings(struct device_node *np) { struct device_node *timings_np; struct device_node *entry; struct device_node *native_mode; struct display_timings *disp; if (!np) { pr_err("%s: no devicenode given\n", of_node_full_name(np)); return NULL; } timings_np = of_find_node_by_name(np, "display-timings"); if (!timings_np) { pr_err("%s: could not find display-timings node\n", of_node_full_name(np)); return NULL; } disp = kzalloc(sizeof(*disp), GFP_KERNEL); if (!disp) { pr_err("%s: could not allocate struct disp'\n", of_node_full_name(np)); goto dispfail; } entry = of_parse_phandle(timings_np, "native-mode", 0); /* assume first child as native mode if none provided */ if (!entry) entry = of_get_next_child(np, NULL); /* if there is no child, it is useless to go on */ if (!entry) { pr_err("%s: no timing specifications given\n", of_node_full_name(np)); goto entryfail; } pr_debug("%s: using %s as default timing\n", of_node_full_name(np), entry->name); native_mode = entry; disp->num_timings = of_get_child_count(timings_np); if (disp->num_timings == 0) { /* should never happen, as entry was already found above */ pr_err("%s: no timings specified\n", of_node_full_name(np)); goto entryfail; } disp->timings = kzalloc(sizeof(struct display_timing *) * disp->num_timings, GFP_KERNEL); if (!disp->timings) { pr_err("%s: could not allocate timings array\n", of_node_full_name(np)); goto entryfail; } disp->num_timings = 0; disp->native_mode = 0; for_each_child_of_node(timings_np, entry) { struct display_timing *dt; dt = of_get_display_timing(entry); if (!dt) { /* * to not encourage wrong devicetrees, fail in case of * an error */ pr_err("%s: error in timing %d\n", of_node_full_name(np), disp->num_timings + 1); goto timingfail; } if (native_mode == entry) disp->native_mode = disp->num_timings; disp->timings[disp->num_timings] = dt; disp->num_timings++; } of_node_put(timings_np); /* * native_mode points to the device_node returned by of_parse_phandle * therefore call of_node_put on it */ of_node_put(native_mode); pr_debug("%s: got %d timings. Using timing #%d as default\n", of_node_full_name(np), disp->num_timings, disp->native_mode + 1); return disp; timingfail: if (native_mode) of_node_put(native_mode); display_timings_release(disp); entryfail: kfree(disp); dispfail: of_node_put(timings_np); return NULL; }