mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-25 12:04:46 +08:00
drm/omap: Expose DRM modes instead of timings in display devices
omap_dss_device operations expose fixed video timings through a .get_timings() operation that return a single timing for the device. To prepare for the move to drm_bridge, modify the API to instead add DRM modes directly to the connector. As this puts more burden on display devices, we also create a helper function for panels to add a single DRM mode from the panel video timings. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This commit is contained in:
parent
d17eb4537a
commit
870e19d59f
@ -68,12 +68,12 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev)
|
|||||||
regulator_disable(ddata->vcc_supply);
|
regulator_disable(ddata->vcc_supply);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
|
static int panel_dpi_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops panel_dpi_ops = {
|
static const struct omap_dss_device_ops panel_dpi_ops = {
|
||||||
@ -83,7 +83,7 @@ static const struct omap_dss_device_ops panel_dpi_ops = {
|
|||||||
.enable = panel_dpi_enable,
|
.enable = panel_dpi_enable,
|
||||||
.disable = panel_dpi_disable,
|
.disable = panel_dpi_disable,
|
||||||
|
|
||||||
.get_timings = panel_dpi_get_timings,
|
.get_modes = panel_dpi_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int panel_dpi_probe_of(struct platform_device *pdev)
|
static int panel_dpi_probe_of(struct platform_device *pdev)
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
|
#include <drm/drm_connector.h>
|
||||||
|
|
||||||
#include <video/mipi_display.h>
|
#include <video/mipi_display.h>
|
||||||
#include <video/of_display_timing.h>
|
#include <video/of_display_timing.h>
|
||||||
|
|
||||||
@ -1110,12 +1112,12 @@ static void dsicm_ulps_work(struct work_struct *work)
|
|||||||
mutex_unlock(&ddata->lock);
|
mutex_unlock(&ddata->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dsicm_get_timings(struct omap_dss_device *dssdev,
|
static int dsicm_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsicm_check_timings(struct omap_dss_device *dssdev,
|
static int dsicm_check_timings(struct omap_dss_device *dssdev,
|
||||||
@ -1156,7 +1158,7 @@ static const struct omap_dss_device_ops dsicm_ops = {
|
|||||||
.enable = dsicm_enable,
|
.enable = dsicm_enable,
|
||||||
.disable = dsicm_disable,
|
.disable = dsicm_disable,
|
||||||
|
|
||||||
.get_timings = dsicm_get_timings,
|
.get_modes = dsicm_get_modes,
|
||||||
.check_timings = dsicm_check_timings,
|
.check_timings = dsicm_check_timings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,12 +139,12 @@ static void lb035q02_disable(struct omap_dss_device *dssdev)
|
|||||||
gpiod_set_value_cansleep(ddata->enable_gpio, 0);
|
gpiod_set_value_cansleep(ddata->enable_gpio, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lb035q02_get_timings(struct omap_dss_device *dssdev,
|
static int lb035q02_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops lb035q02_ops = {
|
static const struct omap_dss_device_ops lb035q02_ops = {
|
||||||
@ -154,7 +154,7 @@ static const struct omap_dss_device_ops lb035q02_ops = {
|
|||||||
.enable = lb035q02_enable,
|
.enable = lb035q02_enable,
|
||||||
.disable = lb035q02_disable,
|
.disable = lb035q02_disable,
|
||||||
|
|
||||||
.get_timings = lb035q02_get_timings,
|
.get_modes = lb035q02_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int lb035q02_probe_of(struct spi_device *spi)
|
static int lb035q02_probe_of(struct spi_device *spi)
|
||||||
|
@ -132,12 +132,12 @@ static void nec_8048_disable(struct omap_dss_device *dssdev)
|
|||||||
gpiod_set_value_cansleep(ddata->res_gpio, 0);
|
gpiod_set_value_cansleep(ddata->res_gpio, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nec_8048_get_timings(struct omap_dss_device *dssdev,
|
static int nec_8048_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops nec_8048_ops = {
|
static const struct omap_dss_device_ops nec_8048_ops = {
|
||||||
@ -147,7 +147,7 @@ static const struct omap_dss_device_ops nec_8048_ops = {
|
|||||||
.enable = nec_8048_enable,
|
.enable = nec_8048_enable,
|
||||||
.disable = nec_8048_disable,
|
.disable = nec_8048_disable,
|
||||||
|
|
||||||
.get_timings = nec_8048_get_timings,
|
.get_modes = nec_8048_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nec_8048_probe(struct spi_device *spi)
|
static int nec_8048_probe(struct spi_device *spi)
|
||||||
|
@ -111,12 +111,12 @@ static void sharp_ls_post_disable(struct omap_dss_device *dssdev)
|
|||||||
regulator_disable(ddata->vcc);
|
regulator_disable(ddata->vcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
|
static int sharp_ls_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops sharp_ls_ops = {
|
static const struct omap_dss_device_ops sharp_ls_ops = {
|
||||||
@ -128,7 +128,7 @@ static const struct omap_dss_device_ops sharp_ls_ops = {
|
|||||||
.disable = sharp_ls_disable,
|
.disable = sharp_ls_disable,
|
||||||
.post_disable = sharp_ls_post_disable,
|
.post_disable = sharp_ls_post_disable,
|
||||||
|
|
||||||
.get_timings = sharp_ls_get_timings,
|
.get_modes = sharp_ls_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
|
static int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
|
||||||
|
@ -596,12 +596,12 @@ static void acx565akm_disable(struct omap_dss_device *dssdev)
|
|||||||
mutex_unlock(&ddata->mutex);
|
mutex_unlock(&ddata->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acx565akm_get_timings(struct omap_dss_device *dssdev,
|
static int acx565akm_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops acx565akm_ops = {
|
static const struct omap_dss_device_ops acx565akm_ops = {
|
||||||
@ -611,7 +611,7 @@ static const struct omap_dss_device_ops acx565akm_ops = {
|
|||||||
.enable = acx565akm_enable,
|
.enable = acx565akm_enable,
|
||||||
.disable = acx565akm_disable,
|
.disable = acx565akm_disable,
|
||||||
|
|
||||||
.get_timings = acx565akm_get_timings,
|
.get_modes = acx565akm_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int acx565akm_probe(struct spi_device *spi)
|
static int acx565akm_probe(struct spi_device *spi)
|
||||||
|
@ -272,12 +272,12 @@ static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
|
|||||||
jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
|
jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
|
static int td028ttec1_panel_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops td028ttec1_ops = {
|
static const struct omap_dss_device_ops td028ttec1_ops = {
|
||||||
@ -287,7 +287,7 @@ static const struct omap_dss_device_ops td028ttec1_ops = {
|
|||||||
.enable = td028ttec1_panel_enable,
|
.enable = td028ttec1_panel_enable,
|
||||||
.disable = td028ttec1_panel_disable,
|
.disable = td028ttec1_panel_disable,
|
||||||
|
|
||||||
.get_timings = td028ttec1_panel_get_timings,
|
.get_modes = td028ttec1_panel_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int td028ttec1_panel_probe(struct spi_device *spi)
|
static int td028ttec1_panel_probe(struct spi_device *spi)
|
||||||
|
@ -347,12 +347,12 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
|
|||||||
tpo_td043_power_off(ddata);
|
tpo_td043_power_off(ddata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
|
static int tpo_td043_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
struct panel_drv_data *ddata = to_panel_data(dssdev);
|
||||||
|
|
||||||
*vm = ddata->vm;
|
return omapdss_display_get_modes(connector, &ddata->vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct omap_dss_device_ops tpo_td043_ops = {
|
static const struct omap_dss_device_ops tpo_td043_ops = {
|
||||||
@ -362,7 +362,7 @@ static const struct omap_dss_device_ops tpo_td043_ops = {
|
|||||||
.enable = tpo_td043_enable,
|
.enable = tpo_td043_enable,
|
||||||
.disable = tpo_td043_disable,
|
.disable = tpo_td043_disable,
|
||||||
|
|
||||||
.get_timings = tpo_td043_get_timings,
|
.get_modes = tpo_td043_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tpo_td043_probe(struct spi_device *spi)
|
static int tpo_td043_probe(struct spi_device *spi)
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
#include <drm/drm_connector.h>
|
||||||
|
#include <drm/drm_modes.h>
|
||||||
|
|
||||||
#include "omapdss.h"
|
#include "omapdss.h"
|
||||||
|
|
||||||
static int disp_num_counter;
|
static int disp_num_counter;
|
||||||
@ -58,3 +61,22 @@ struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
|
|||||||
return omapdss_device_get(output);
|
return omapdss_device_get(output);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(omapdss_display_get);
|
EXPORT_SYMBOL_GPL(omapdss_display_get);
|
||||||
|
|
||||||
|
int omapdss_display_get_modes(struct drm_connector *connector,
|
||||||
|
const struct videomode *vm)
|
||||||
|
{
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
|
||||||
|
mode = drm_mode_create(connector->dev);
|
||||||
|
if (!mode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
drm_display_mode_from_videomode(vm, mode);
|
||||||
|
|
||||||
|
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||||
|
drm_mode_set_name(mode);
|
||||||
|
drm_mode_probed_add(connector, mode);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(omapdss_display_get_modes);
|
||||||
|
@ -67,6 +67,7 @@ struct dss_lcd_mgr_config;
|
|||||||
struct snd_aes_iec958;
|
struct snd_aes_iec958;
|
||||||
struct snd_cea_861_aud_if;
|
struct snd_cea_861_aud_if;
|
||||||
struct hdmi_avi_infoframe;
|
struct hdmi_avi_infoframe;
|
||||||
|
struct drm_connector;
|
||||||
|
|
||||||
enum omap_display_type {
|
enum omap_display_type {
|
||||||
OMAP_DISPLAY_TYPE_NONE = 0,
|
OMAP_DISPLAY_TYPE_NONE = 0,
|
||||||
@ -366,8 +367,6 @@ struct omap_dss_device_ops {
|
|||||||
|
|
||||||
int (*check_timings)(struct omap_dss_device *dssdev,
|
int (*check_timings)(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm);
|
struct videomode *vm);
|
||||||
void (*get_timings)(struct omap_dss_device *dssdev,
|
|
||||||
struct videomode *vm);
|
|
||||||
void (*set_timings)(struct omap_dss_device *dssdev,
|
void (*set_timings)(struct omap_dss_device *dssdev,
|
||||||
const struct videomode *vm);
|
const struct videomode *vm);
|
||||||
|
|
||||||
@ -381,6 +380,9 @@ struct omap_dss_device_ops {
|
|||||||
|
|
||||||
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
|
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
|
||||||
|
|
||||||
|
int (*get_modes)(struct omap_dss_device *dssdev,
|
||||||
|
struct drm_connector *connector);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
const struct omapdss_hdmi_ops hdmi;
|
const struct omapdss_hdmi_ops hdmi;
|
||||||
const struct omapdss_dsi_ops dsi;
|
const struct omapdss_dsi_ops dsi;
|
||||||
@ -469,6 +471,8 @@ static inline bool omapdss_is_initialized(void)
|
|||||||
|
|
||||||
void omapdss_display_init(struct omap_dss_device *dssdev);
|
void omapdss_display_init(struct omap_dss_device *dssdev);
|
||||||
struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
|
struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
|
||||||
|
int omapdss_display_get_modes(struct drm_connector *connector,
|
||||||
|
const struct videomode *vm);
|
||||||
|
|
||||||
void omapdss_device_register(struct omap_dss_device *dssdev);
|
void omapdss_device_register(struct omap_dss_device *dssdev);
|
||||||
void omapdss_device_unregister(struct omap_dss_device *dssdev);
|
void omapdss_device_unregister(struct omap_dss_device *dssdev);
|
||||||
|
@ -548,14 +548,17 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
|
|||||||
mutex_unlock(&venc->venc_lock);
|
mutex_unlock(&venc->venc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void venc_get_timings(struct omap_dss_device *dssdev,
|
static int venc_get_modes(struct omap_dss_device *dssdev,
|
||||||
struct videomode *vm)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct venc_device *venc = dssdev_to_venc(dssdev);
|
struct venc_device *venc = dssdev_to_venc(dssdev);
|
||||||
|
int r;
|
||||||
|
|
||||||
mutex_lock(&venc->venc_lock);
|
mutex_lock(&venc->venc_lock);
|
||||||
*vm = venc->vm;
|
r = omapdss_display_get_modes(connector, &venc->vm);
|
||||||
mutex_unlock(&venc->venc_lock);
|
mutex_unlock(&venc->venc_lock);
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void venc_set_timings(struct omap_dss_device *dssdev,
|
static void venc_set_timings(struct omap_dss_device *dssdev,
|
||||||
@ -690,8 +693,9 @@ static const struct omap_dss_device_ops venc_ops = {
|
|||||||
.disable = venc_display_disable,
|
.disable = venc_display_disable,
|
||||||
|
|
||||||
.check_timings = venc_check_timings,
|
.check_timings = venc_check_timings,
|
||||||
.get_timings = venc_get_timings,
|
|
||||||
.set_timings = venc_set_timings,
|
.set_timings = venc_set_timings,
|
||||||
|
|
||||||
|
.get_modes = venc_get_modes,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
@ -212,8 +212,6 @@ static int omap_connector_get_modes(struct drm_connector *connector)
|
|||||||
{
|
{
|
||||||
struct omap_connector *omap_connector = to_omap_connector(connector);
|
struct omap_connector *omap_connector = to_omap_connector(connector);
|
||||||
struct omap_dss_device *dssdev;
|
struct omap_dss_device *dssdev;
|
||||||
struct drm_display_mode *mode;
|
|
||||||
struct videomode vm = {0};
|
|
||||||
|
|
||||||
DBG("%s", omap_connector->display->name);
|
DBG("%s", omap_connector->display->name);
|
||||||
|
|
||||||
@ -238,31 +236,20 @@ static int omap_connector_get_modes(struct drm_connector *connector)
|
|||||||
&connector->display_info.height_mm);
|
&connector->display_info.height_mm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over the pipeline to find the first device that can provide
|
* If the display pipeline reports modes (e.g. with a fixed resolution
|
||||||
* timing information. If we can't find any, we just let the KMS core
|
* panel or an analog TV output), query it.
|
||||||
* add the default modes.
|
|
||||||
*/
|
*/
|
||||||
for (dssdev = omap_connector->display; dssdev; dssdev = dssdev->src) {
|
for (dssdev = omap_connector->display; dssdev; dssdev = dssdev->src) {
|
||||||
if (dssdev->ops->get_timings)
|
if (dssdev->ops->get_modes)
|
||||||
break;
|
return dssdev->ops->get_modes(dssdev, connector);
|
||||||
}
|
}
|
||||||
if (!dssdev)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Add a single mode corresponding to the fixed panel timings. */
|
/*
|
||||||
mode = drm_mode_create(connector->dev);
|
* We can't retrieve modes, which can happen for instance for a DVI or
|
||||||
if (!mode)
|
* VGA output with the DDC bus unconnected. The KMS core will add the
|
||||||
return 0;
|
* default modes.
|
||||||
|
*/
|
||||||
dssdev->ops->get_timings(dssdev, &vm);
|
return 0;
|
||||||
|
|
||||||
drm_display_mode_from_videomode(&vm, mode);
|
|
||||||
|
|
||||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
|
||||||
drm_mode_set_name(mode);
|
|
||||||
drm_mode_probed_add(connector, mode);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_connector_mode_valid(struct drm_connector *connector,
|
static int omap_connector_mode_valid(struct drm_connector *connector,
|
||||||
|
Loading…
Reference in New Issue
Block a user