static int __exit tpd_remove(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct omap_dss_device *dssdev = &ddata->dssdev; struct omap_dss_device *in = ddata->in; tpd_uninit_pins(pdev); unregister_pm_notifier(&hdmi_i2c2_hack_pm_notif_block); hdmi_i2c2_hack_suspend_mcasp(); omapdss_unregister_output(&ddata->dssdev); WARN_ON(omapdss_device_is_enabled(dssdev)); if (omapdss_device_is_enabled(dssdev)) tpd_disable(dssdev); WARN_ON(omapdss_device_is_connected(dssdev)); if (omapdss_device_is_connected(dssdev)) tpd_disconnect(dssdev, dssdev->dst); omap_dss_put_device(in); return 0; }
static ssize_t display_enabled_store(struct omap_dss_device *dssdev, const char *buf, size_t size) { int r; bool enable; r = strtobool(buf, &enable); if (r) return r; if (enable == omapdss_device_is_enabled(dssdev)) return size; if (omapdss_device_is_connected(dssdev) == false) return -ENODEV; if (enable) { r = dssdev->driver->enable(dssdev); if (r) return r; } else { dssdev->driver->disable(dssdev); } return size; }
static int tfp410_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; in->ops.dpi->set_timings(in, &ddata->timings); if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); r = in->ops.dpi->enable(in); if (r) return r; if (gpio_is_valid(ddata->pd_gpio)) gpio_set_value_cansleep(ddata->pd_gpio, 1); dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int opa362_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; dev_dbg(dssdev->dev, "enable\n"); if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; in->ops.atv->set_timings(in, &ddata->timings); r = in->ops.atv->enable(in); if (r) return r; if (ddata->enable_gpio) gpiod_set_value_cansleep(ddata->enable_gpio, 1); dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int panel_dpi_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *src = dssdev->src; int r; if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; r = src->ops->enable(src); if (r) return r; r = regulator_enable(ddata->vcc_supply); if (r) { src->ops->disable(src); return r; } gpiod_set_value_cansleep(ddata->enable_gpio, 1); backlight_enable(ddata->backlight); dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int panel_dpi_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); in->ops.dpi->set_timings(in, &ddata->vm); r = in->ops.dpi->enable(in); if (r) return r; r = regulator_enable(ddata->vcc_supply); if (r) { in->ops.dpi->disable(in); return r; } gpiod_set_value_cansleep(ddata->enable_gpio, 1); if (gpio_is_valid(ddata->backlight_gpio)) gpio_set_value_cansleep(ddata->backlight_gpio, 1); dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static void dvic_disconnect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; if (!omapdss_device_is_connected(dssdev)) return; in->ops.dvi->disconnect(in, dssdev); }
static void tfp410_disconnect(struct omap_dss_device *dssdev, struct omap_dss_device *dst) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; WARN_ON(!omapdss_device_is_connected(dssdev)); if (!omapdss_device_is_connected(dssdev)) return; WARN_ON(dst != dssdev->dst); if (dst != dssdev->dst) return; dst->src = NULL; dssdev->dst = NULL; in->ops.dpi->disconnect(in, &ddata->dssdev); }
static int __exit opa362_remove(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct omap_dss_device *dssdev = &ddata->dssdev; struct omap_dss_device *in = ddata->in; omapdss_unregister_output(&ddata->dssdev); WARN_ON(omapdss_device_is_enabled(dssdev)); if (omapdss_device_is_enabled(dssdev)) opa362_disable(dssdev); WARN_ON(omapdss_device_is_connected(dssdev)); if (omapdss_device_is_connected(dssdev)) opa362_disconnect(dssdev, dssdev->dst); omap_dss_put_device(in); return 0; }
static void acx565akm_disconnect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; if (!omapdss_device_is_connected(dssdev)) return; in->ops.sdi->disconnect(in, dssdev); omap_dss_put_device(in); ddata->in = NULL; }
static int dvic_connect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (omapdss_device_is_connected(dssdev)) return 0; r = in->ops.dvi->connect(in, dssdev); if (r) return r; return 0; }
static int tfp410_connect(struct omap_dss_device *dssdev, struct omap_dss_device *dst) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (omapdss_device_is_connected(dssdev)) return -EBUSY; r = in->ops.dpi->connect(in, dssdev); if (r) return r; dst->src = dssdev; dssdev->dst = dst; return 0; }
static int dvic_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; in->ops.dvi->set_timings(in, &ddata->timings); r = in->ops.dvi->enable(in); if (r) return r; dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int acx565akm_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); int r; dev_dbg(dssdev->dev, "%s\n", __func__); if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; mutex_lock(&ddata->mutex); r = acx565akm_panel_power_on(dssdev); mutex_unlock(&ddata->mutex); if (r) return r; dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int tpo_td043_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; int r; if (!omapdss_device_is_connected(dssdev)) return -ENODEV; if (omapdss_device_is_enabled(dssdev)) return 0; if (ddata->data_lines) in->ops.dpi->set_data_lines(in, ddata->data_lines); in->ops.dpi->set_timings(in, &ddata->videomode); r = in->ops.dpi->enable(in); if (r) return r; /* * If we are resuming from system suspend, SPI clocks might not be * enabled yet, so we'll program the LCD from SPI PM resume callback. */ if (!ddata->spi_suspended) { r = tpo_td043_power_on(ddata); if (r) { in->ops.dpi->disable(in); return r; } } dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; }
static int acx565akm_connect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in; int r; if (omapdss_device_is_connected(dssdev)) return 0; in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node); if (IS_ERR(in)) { dev_err(dssdev->dev, "failed to find video source\n"); return PTR_ERR(in); } r = in->ops.sdi->connect(in, dssdev); if (r) { omap_dss_put_device(in); return r; } ddata->in = in; return 0; }
static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_dss_device *dssdev = NULL; int num_ovls = dss_feat_get_num_ovls(); int num_mgrs = dss_feat_get_num_mgrs(); int num_crtcs; int i, id = 0; drm_mode_config_init(dev); omap_drm_irq_install(dev); /* * We usually don't want to create a CRTC for each manager, at least * not until we have a way to expose private planes to userspace. * Otherwise there would not be enough video pipes left for drm planes. * We use the num_crtc argument to limit the number of crtcs we create. */ num_crtcs = min3(num_crtc, num_mgrs, num_ovls); dssdev = NULL; for_each_dss_dev(dssdev) { struct drm_connector *connector; struct drm_encoder *encoder; enum omap_channel channel; struct omap_overlay_manager *mgr; if (!omapdss_device_is_connected(dssdev)) continue; encoder = omap_encoder_init(dev, dssdev); if (!encoder) { dev_err(dev->dev, "could not create encoder: %s\n", dssdev->name); return -ENOMEM; } connector = omap_connector_init(dev, get_connector_type(dssdev), dssdev, encoder); if (!connector) { dev_err(dev->dev, "could not create connector: %s\n", dssdev->name); return -ENOMEM; } BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); priv->encoders[priv->num_encoders++] = encoder; priv->connectors[priv->num_connectors++] = connector; drm_mode_connector_attach_encoder(connector, encoder); /* * if we have reached the limit of the crtcs we are allowed to * create, let's not try to look for a crtc for this * panel/encoder and onwards, we will, of course, populate the * the possible_crtcs field for all the encoders with the final * set of crtcs we create */ if (id == num_crtcs) continue; /* * get the recommended DISPC channel for this encoder. For now, * we only try to get create a crtc out of the recommended, the * other possible channels to which the encoder can connect are * not considered. */ mgr = omapdss_find_mgr_from_display(dssdev); channel = mgr->id; /* * if this channel hasn't already been taken by a previously * allocated crtc, we create a new crtc for it */ if (!channel_used(dev, channel)) { struct drm_plane *plane; struct drm_crtc *crtc; plane = omap_plane_init(dev, id, true); crtc = omap_crtc_init(dev, plane, channel, id); BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); priv->crtcs[id] = crtc; priv->num_crtcs++; priv->planes[id] = plane; priv->num_planes++; id++; } } /* * we have allocated crtcs according to the need of the panels/encoders, * adding more crtcs here if needed */ for (; id < num_crtcs; id++) { /* find a free manager for this crtc */ for (i = 0; i < num_mgrs; i++) { if (!channel_used(dev, i)) { struct drm_plane *plane; struct drm_crtc *crtc; plane = omap_plane_init(dev, id, true); crtc = omap_crtc_init(dev, plane, i, id); BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); priv->crtcs[id] = crtc; priv->num_crtcs++; priv->planes[id] = plane; priv->num_planes++; break; } else { continue; } } if (i == num_mgrs) { /* this shouldn't really happen */ dev_err(dev->dev, "no managers left for crtc\n"); return -ENOMEM; } } /* * Create normal planes for the remaining overlays: */ for (; id < num_ovls; id++) { struct drm_plane *plane = omap_plane_init(dev, id, false); BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); priv->planes[priv->num_planes++] = plane; } for (i = 0; i < priv->num_encoders; i++) { struct drm_encoder *encoder = priv->encoders[i]; struct omap_dss_device *dssdev = omap_encoder_get_dssdev(encoder); struct omap_dss_device *output; output = omapdss_find_output_from_display(dssdev); /* figure out which crtc's we can connect the encoder to: */ encoder->possible_crtcs = 0; for (id = 0; id < priv->num_crtcs; id++) { struct drm_crtc *crtc = priv->crtcs[id]; enum omap_channel crtc_channel; crtc_channel = omap_crtc_channel(crtc); if (output->dispc_channel == crtc_channel) { encoder->possible_crtcs |= (1 << id); break; } } omap_dss_put_device(output); } DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", priv->num_planes, priv->num_crtcs, priv->num_encoders, priv->num_connectors); dev->mode_config.min_width = 32; dev->mode_config.min_height = 32; /* note: eventually will need some cpu_is_omapXYZ() type stuff here * to fill in these limits properly on different OMAP generations.. */ dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; dev->mode_config.funcs = &omap_mode_config_funcs; return 0; }
static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_dss_device *dssdev = NULL; int num_ovls = priv->dispc_ops->get_num_ovls(); int num_mgrs = priv->dispc_ops->get_num_mgrs(); int num_crtcs, crtc_idx, plane_idx; int ret; u32 plane_crtc_mask; drm_mode_config_init(dev); ret = omap_modeset_init_properties(dev); if (ret < 0) return ret; /* * This function creates exactly one connector, encoder, crtc, * and primary plane per each connected dss-device. Each * connector->encoder->crtc chain is expected to be separate * and each crtc is connect to a single dss-channel. If the * configuration does not match the expectations or exceeds * the available resources, the configuration is rejected. */ num_crtcs = 0; for_each_dss_dev(dssdev) if (omapdss_device_is_connected(dssdev)) num_crtcs++; if (num_crtcs > num_mgrs || num_crtcs > num_ovls || num_crtcs > ARRAY_SIZE(priv->crtcs) || num_crtcs > ARRAY_SIZE(priv->planes) || num_crtcs > ARRAY_SIZE(priv->encoders) || num_crtcs > ARRAY_SIZE(priv->connectors)) { dev_err(dev->dev, "%s(): Too many connected displays\n", __func__); return -EINVAL; } /* All planes can be put to any CRTC */ plane_crtc_mask = (1 << num_crtcs) - 1; dssdev = NULL; crtc_idx = 0; plane_idx = 0; for_each_dss_dev(dssdev) { struct drm_connector *connector; struct drm_encoder *encoder; struct drm_plane *plane; struct drm_crtc *crtc; if (!omapdss_device_is_connected(dssdev)) continue; encoder = omap_encoder_init(dev, dssdev); if (!encoder) return -ENOMEM; connector = omap_connector_init(dev, get_connector_type(dssdev), dssdev, encoder); if (!connector) return -ENOMEM; plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_PRIMARY, plane_crtc_mask); if (IS_ERR(plane)) return PTR_ERR(plane); crtc = omap_crtc_init(dev, plane, dssdev); if (IS_ERR(crtc)) return PTR_ERR(crtc); drm_mode_connector_attach_encoder(connector, encoder); encoder->possible_crtcs = (1 << crtc_idx); priv->crtcs[priv->num_crtcs++] = crtc; priv->planes[priv->num_planes++] = plane; priv->encoders[priv->num_encoders++] = encoder; priv->connectors[priv->num_connectors++] = connector; plane_idx++; crtc_idx++; } /* * Create normal planes for the remaining overlays: */ for (; plane_idx < num_ovls; plane_idx++) { struct drm_plane *plane; if (WARN_ON(priv->num_planes >= ARRAY_SIZE(priv->planes))) return -EINVAL; plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_OVERLAY, plane_crtc_mask); if (IS_ERR(plane)) return PTR_ERR(plane); priv->planes[priv->num_planes++] = plane; } DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", priv->num_planes, priv->num_crtcs, priv->num_encoders, priv->num_connectors); dev->mode_config.min_width = 8; dev->mode_config.min_height = 2; /* note: eventually will need some cpu_is_omapXYZ() type stuff here * to fill in these limits properly on different OMAP generations.. */ dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; dev->mode_config.funcs = &omap_mode_config_funcs; dev->mode_config.helper_private = &omap_mode_config_helper_funcs; drm_mode_config_reset(dev); omap_drm_irq_install(dev); return 0; }