diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/core.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dispc.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dss.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/output.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_dmm_tiler.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fb.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.c | 137 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 2 |
14 files changed, 239 insertions, 195 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile index 904101c5e79d..5950c3f52c2e 100644 --- a/drivers/gpu/drm/omapdrm/dss/Makefile +++ b/drivers/gpu/drm/omapdrm/dss/Makefile @@ -6,7 +6,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o obj-$(CONFIG_OMAP2_DSS) += omapdss.o # Core DSS files -omapdss-y := core.o dss.o dispc.o dispc_coefs.o \ +omapdss-y := dss.o dispc.o dispc_coefs.o \ pll.o video-pll.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c deleted file mode 100644 index 6ac497b63711..000000000000 --- a/drivers/gpu/drm/omapdrm/dss/core.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2009 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> - * - * Some code and ideas taken from drivers/video/omap/ driver - * by Imre Deak. - */ - -#define DSS_SUBSYS_NAME "CORE" - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> - -#include "omapdss.h" -#include "dss.h" - -/* INIT */ -static struct platform_driver * const omap_dss_drivers[] = { - &omap_dsshw_driver, - &omap_dispchw_driver, -#ifdef CONFIG_OMAP2_DSS_DSI - &omap_dsihw_driver, -#endif -#ifdef CONFIG_OMAP2_DSS_VENC - &omap_venchw_driver, -#endif -#ifdef CONFIG_OMAP4_DSS_HDMI - &omapdss_hdmi4hw_driver, -#endif -#ifdef CONFIG_OMAP5_DSS_HDMI - &omapdss_hdmi5hw_driver, -#endif -}; - -static int __init omap_dss_init(void) -{ - return platform_register_drivers(omap_dss_drivers, - ARRAY_SIZE(omap_dss_drivers)); -} - -static void __exit omap_dss_exit(void) -{ - platform_unregister_drivers(omap_dss_drivers, - ARRAY_SIZE(omap_dss_drivers)); -} - -module_init(omap_dss_init); -module_exit(omap_dss_exit); - -MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); -MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); -MODULE_LICENSE("GPL v2"); - diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index ed0ccbeed70f..413dbdd1771e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -114,6 +114,7 @@ struct dispc_features { const unsigned int num_reg_fields; const enum omap_overlay_caps *overlay_caps; const u32 **supported_color_modes; + const u32 *supported_scaler_color_modes; unsigned int num_mgrs; unsigned int num_ovls; unsigned int buffer_size_unit; @@ -184,9 +185,6 @@ struct dispc_device { struct regmap *syscon_pol; u32 syscon_pol_offset; - - /* DISPC_CONTROL & DISPC_CONFIG lock*/ - spinlock_t control_lock; }; enum omap_color_component { @@ -368,25 +366,17 @@ static inline u32 dispc_read_reg(struct dispc_device *dispc, u16 idx) static u32 mgr_fld_read(struct dispc_device *dispc, enum omap_channel channel, enum mgr_reg_fields regfld) { - const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld]; + const struct dispc_reg_field *rfld = &mgr_desc[channel].reg_desc[regfld]; - return REG_GET(dispc, rfld.reg, rfld.high, rfld.low); + return REG_GET(dispc, rfld->reg, rfld->high, rfld->low); } static void mgr_fld_write(struct dispc_device *dispc, enum omap_channel channel, enum mgr_reg_fields regfld, int val) { - const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld]; - const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG; - unsigned long flags; + const struct dispc_reg_field *rfld = &mgr_desc[channel].reg_desc[regfld]; - if (need_lock) { - spin_lock_irqsave(&dispc->control_lock, flags); - REG_FLD_MOD(dispc, rfld.reg, val, rfld.high, rfld.low); - spin_unlock_irqrestore(&dispc->control_lock, flags); - } else { - REG_FLD_MOD(dispc, rfld.reg, val, rfld.high, rfld.low); - } + REG_FLD_MOD(dispc, rfld->reg, val, rfld->high, rfld->low); } static int dispc_get_num_ovls(struct dispc_device *dispc) @@ -2510,6 +2500,19 @@ static int dispc_ovl_calc_scaling(struct dispc_device *dispc, if (width == out_width && height == out_height) return 0; + if (dispc->feat->supported_scaler_color_modes) { + const u32 *modes = dispc->feat->supported_scaler_color_modes; + unsigned int i; + + for (i = 0; modes[i]; ++i) { + if (modes[i] == fourcc) + break; + } + + if (modes[i] == 0) + return -EINVAL; + } + if (plane == OMAP_DSS_WB) { switch (fourcc) { case DRM_FORMAT_NV12: @@ -4225,6 +4228,12 @@ static const u32 *omap4_dispc_supported_color_modes[] = { DRM_FORMAT_RGBX8888), }; +static const u32 omap3_dispc_supported_scaler_color_modes[] = { + DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + 0, +}; + static const struct dispc_features omap24xx_dispc_feats = { .sw_start = 5, .fp_start = 15, @@ -4253,6 +4262,7 @@ static const struct dispc_features omap24xx_dispc_feats = { .num_reg_fields = ARRAY_SIZE(omap2_dispc_reg_fields), .overlay_caps = omap2_dispc_overlay_caps, .supported_color_modes = omap2_dispc_supported_color_modes, + .supported_scaler_color_modes = COLOR_ARRAY(DRM_FORMAT_XRGB8888), .num_mgrs = 2, .num_ovls = 3, .buffer_size_unit = 1, @@ -4287,6 +4297,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), .overlay_caps = omap3430_dispc_overlay_caps, .supported_color_modes = omap3_dispc_supported_color_modes, + .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes, .num_mgrs = 2, .num_ovls = 3, .buffer_size_unit = 1, @@ -4321,6 +4332,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), .overlay_caps = omap3430_dispc_overlay_caps, .supported_color_modes = omap3_dispc_supported_color_modes, + .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes, .num_mgrs = 2, .num_ovls = 3, .buffer_size_unit = 1, @@ -4355,6 +4367,7 @@ static const struct dispc_features omap36xx_dispc_feats = { .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), .overlay_caps = omap3630_dispc_overlay_caps, .supported_color_modes = omap3_dispc_supported_color_modes, + .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes, .num_mgrs = 2, .num_ovls = 3, .buffer_size_unit = 1, @@ -4389,6 +4402,7 @@ static const struct dispc_features am43xx_dispc_feats = { .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), .overlay_caps = omap3430_dispc_overlay_caps, .supported_color_modes = omap3_dispc_supported_color_modes, + .supported_scaler_color_modes = omap3_dispc_supported_scaler_color_modes, .num_mgrs = 1, .num_ovls = 3, .buffer_size_unit = 1, @@ -4768,8 +4782,6 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) platform_set_drvdata(pdev, dispc); dispc->dss = dss; - spin_lock_init(&dispc->control_lock); - /* * The OMAP3-based models can't be told apart using the compatible * string, use SoC device matching. diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index b30fcaa2d0f5..da16ea095f13 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -3548,7 +3548,7 @@ static int dsi_proto_config(struct dsi_data *dsi) static void dsi_proto_timings(struct dsi_data *dsi) { - unsigned int tlpx, tclk_zero, tclk_prepare, tclk_trail; + unsigned int tlpx, tclk_zero, tclk_prepare; unsigned int tclk_pre, tclk_post; unsigned int ths_prepare, ths_prepare_ths_zero, ths_zero; unsigned int ths_trail, ths_exit; @@ -3567,7 +3567,6 @@ static void dsi_proto_timings(struct dsi_data *dsi) r = dsi_read_reg(dsi, DSI_DSIPHY_CFG1); tlpx = FLD_GET(r, 20, 16) * 2; - tclk_trail = FLD_GET(r, 15, 8); tclk_zero = FLD_GET(r, 7, 0); r = dsi_read_reg(dsi, DSI_DSIPHY_CFG2); diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 4bdd63b57100..225ec808b01a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1598,3 +1598,40 @@ struct platform_driver omap_dsshw_driver = { .suppress_bind_attrs = true, }, }; + +/* INIT */ +static struct platform_driver * const omap_dss_drivers[] = { + &omap_dsshw_driver, + &omap_dispchw_driver, +#ifdef CONFIG_OMAP2_DSS_DSI + &omap_dsihw_driver, +#endif +#ifdef CONFIG_OMAP2_DSS_VENC + &omap_venchw_driver, +#endif +#ifdef CONFIG_OMAP4_DSS_HDMI + &omapdss_hdmi4hw_driver, +#endif +#ifdef CONFIG_OMAP5_DSS_HDMI + &omapdss_hdmi5hw_driver, +#endif +}; + +static int __init omap_dss_init(void) +{ + return platform_register_drivers(omap_dss_drivers, + ARRAY_SIZE(omap_dss_drivers)); +} + +static void __exit omap_dss_exit(void) +{ + platform_unregister_drivers(omap_dss_drivers, + ARRAY_SIZE(omap_dss_drivers)); +} + +module_init(omap_dss_init); +module_exit(omap_dss_exit); + +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); +MODULE_DESCRIPTION("OMAP2/3/4/5 Display Subsystem"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index 5d5d5588ebc1..ea5d5c228534 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -542,8 +542,9 @@ static void hdmi_core_audio_config(struct hdmi_core_data *core, } /* Set ACR clock divisor */ - REG_FLD_MOD(av_base, - HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); + if (cfg->use_mclk) + REG_FLD_MOD(av_base, HDMI_CORE_AV_FREQ_SVAL, + cfg->mclk_mode, 2, 0); r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); /* @@ -675,7 +676,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_audio_format audio_format; struct hdmi_audio_dma audio_dma; struct hdmi_core_audio_config acore; - int err, n, cts, channel_count; + int n, cts, channel_count; unsigned int fs_nr; bool word_length_16b = false; @@ -737,7 +738,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, return -EINVAL; } - err = hdmi_compute_acr(pclk, fs_nr, &n, &cts); + hdmi_compute_acr(pclk, fs_nr, &n, &cts); /* Audio clock regeneration settings */ acore.n = n; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 7400fb99d453..ff4d35c8771f 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -23,24 +23,12 @@ #include "hdmi5_core.h" -/* only 24 bit color depth used for now */ -static const struct csc_table csc_table_deepcolor[] = { - /* HDMI_DEEP_COLOR_24BIT */ - [0] = { 7036, 0, 0, 32, 0, 7036, 0, 32, 0, 0, 7036, 32, }, - /* HDMI_DEEP_COLOR_30BIT */ - [1] = { 7015, 0, 0, 128, 0, 7015, 0, 128, 0, 0, 7015, 128, }, - /* HDMI_DEEP_COLOR_36BIT */ - [2] = { 7010, 0, 0, 512, 0, 7010, 0, 512, 0, 0, 7010, 512, }, - /* FULL RANGE */ - [3] = { 8192, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 8192, 0, }, -}; - static void hdmi_core_ddc_init(struct hdmi_core_data *core) { void __iomem *base = core->base; const unsigned long long iclk = 266000000; /* DSS L3 ICLK */ - const unsigned int ss_scl_high = 4600; /* ns */ - const unsigned int ss_scl_low = 5400; /* ns */ + const unsigned int ss_scl_high = 4700; /* ns */ + const unsigned int ss_scl_low = 5500; /* ns */ const unsigned int fs_scl_high = 600; /* ns */ const unsigned int fs_scl_low = 1300; /* ns */ const unsigned int sda_hold = 1000; /* ns */ @@ -397,14 +385,6 @@ static void hdmi_core_config_video_packetizer(struct hdmi_core_data *core) REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 0 : 2, 1, 0); } -static void hdmi_core_config_csc(struct hdmi_core_data *core) -{ - int clr_depth = 0; /* 24 bit color depth */ - - /* CSC_COLORDEPTH */ - REG_FLD_MOD(core->base, HDMI_CORE_CSC_SCALE, clr_depth, 7, 4); -} - static void hdmi_core_config_video_sampler(struct hdmi_core_data *core) { int video_mapping = 1; /* for 24 bit color depth */ @@ -469,47 +449,67 @@ static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core, REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, pr, 3, 0); } -static void hdmi_core_csc_config(struct hdmi_core_data *core, - struct csc_table csc_coeff) +static void hdmi_core_write_csc(struct hdmi_core_data *core, + const struct csc_table *csc_coeff) { void __iomem *base = core->base; - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_MSB, csc_coeff.a1 >> 8 , 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_LSB, csc_coeff.a1, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_MSB, csc_coeff.a2 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_LSB, csc_coeff.a2, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_MSB, csc_coeff.a3 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_LSB, csc_coeff.a3, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_MSB, csc_coeff.a4 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_LSB, csc_coeff.a4, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_MSB, csc_coeff.b1 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_LSB, csc_coeff.b1, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_MSB, csc_coeff.b2 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_LSB, csc_coeff.b2, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_MSB, csc_coeff.b3 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_LSB, csc_coeff.b3, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_MSB, csc_coeff.b4 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_LSB, csc_coeff.b4, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_MSB, csc_coeff.c1 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_LSB, csc_coeff.c1, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_MSB, csc_coeff.c2 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_LSB, csc_coeff.c2, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_MSB, csc_coeff.c3 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_LSB, csc_coeff.c3, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_MSB, csc_coeff.c4 >> 8, 6, 0); - REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_LSB, csc_coeff.c4, 7, 0); - + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_MSB, csc_coeff->a1 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_LSB, csc_coeff->a1, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_MSB, csc_coeff->a2 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_LSB, csc_coeff->a2, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_MSB, csc_coeff->a3 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_LSB, csc_coeff->a3, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_MSB, csc_coeff->a4 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_LSB, csc_coeff->a4, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_MSB, csc_coeff->b1 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_LSB, csc_coeff->b1, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_MSB, csc_coeff->b2 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_LSB, csc_coeff->b2, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_MSB, csc_coeff->b3 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_LSB, csc_coeff->b3, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_MSB, csc_coeff->b4 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_LSB, csc_coeff->b4, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_MSB, csc_coeff->c1 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_LSB, csc_coeff->c1, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_MSB, csc_coeff->c2 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_LSB, csc_coeff->c2, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_MSB, csc_coeff->c3 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_LSB, csc_coeff->c3, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_MSB, csc_coeff->c4 >> 8, 6, 0); + REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_LSB, csc_coeff->c4, 7, 0); + + /* enable CSC */ REG_FLD_MOD(base, HDMI_CORE_MC_FLOWCTRL, 0x1, 0, 0); } -static void hdmi_core_configure_range(struct hdmi_core_data *core) +static void hdmi_core_configure_range(struct hdmi_core_data *core, + enum hdmi_quantization_range range) { - struct csc_table csc_coeff = { 0 }; + static const struct csc_table csc_limited_range = { + 7036, 0, 0, 32, 0, 7036, 0, 32, 0, 0, 7036, 32 + }; + static const struct csc_table csc_full_range = { + 8192, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 8192, 0 + }; + const struct csc_table *csc_coeff; + + /* CSC_COLORDEPTH = 24 bits*/ + REG_FLD_MOD(core->base, HDMI_CORE_CSC_SCALE, 0, 7, 4); + + switch (range) { + case HDMI_QUANTIZATION_RANGE_FULL: + csc_coeff = &csc_full_range; + break; - /* support limited range with 24 bit color depth for now */ - csc_coeff = csc_table_deepcolor[0]; + case HDMI_QUANTIZATION_RANGE_DEFAULT: + case HDMI_QUANTIZATION_RANGE_LIMITED: + default: + csc_coeff = &csc_limited_range; + break; + } - hdmi_core_csc_config(core, csc_coeff); + hdmi_core_write_csc(core, csc_coeff); } static void hdmi_core_enable_video_path(struct hdmi_core_data *core) @@ -600,9 +600,20 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct videomode vm; struct hdmi_video_format video_format; struct hdmi_core_vid_config v_core_cfg; + enum hdmi_quantization_range range; hdmi_core_mask_interrupts(core); + if (cfg->hdmi_dvi_mode == HDMI_HDMI) { + char vic = cfg->infoframe.video_code; + + /* All CEA modes other than VIC 1 use limited quantization range. */ + range = vic > 1 ? HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL; + } else { + range = HDMI_QUANTIZATION_RANGE_FULL; + } + hdmi_core_init(&v_core_cfg, cfg); hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg); @@ -616,9 +627,8 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, hdmi_wp_video_config_interface(wp, &vm); - /* support limited range with 24 bit color depth for now */ - hdmi_core_configure_range(core); - cfg->infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; + hdmi_core_configure_range(core, range); + cfg->infoframe.quantization_range = range; /* * configure core video part, set software reset in the core @@ -628,7 +638,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, hdmi_core_video_config(core, &v_core_cfg); hdmi_core_config_video_packetizer(core); - hdmi_core_config_csc(core); hdmi_core_config_video_sampler(core); if (cfg->hdmi_dvi_mode == HDMI_HDMI) @@ -798,7 +807,7 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_audio_format audio_format; struct hdmi_audio_dma audio_dma; struct hdmi_core_audio_config core_cfg; - int err, n, cts, channel_count; + int n, cts, channel_count; unsigned int fs_nr; bool word_length_16b = false; @@ -841,7 +850,7 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, return -EINVAL; } - err = hdmi_compute_acr(pclk, fs_nr, &n, &cts); + hdmi_compute_acr(pclk, fs_nr, &n, &cts); core_cfg.n = n; core_cfg.cts = cts; diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c index 14b41de44ebc..0693d34fca1b 100644 --- a/drivers/gpu/drm/omapdrm/dss/output.c +++ b/drivers/gpu/drm/omapdrm/dss/output.c @@ -12,6 +12,7 @@ #include <linux/of.h> #include <linux/of_graph.h> +#include <drm/drm_bridge.h> #include <drm/drm_panel.h> #include "dss.h" diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h index 835e6654fa82..43c1d096b021 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h @@ -113,7 +113,7 @@ extern struct platform_driver omap_dmm_driver; /* GEM bo flags -> tiler fmt */ static inline enum tiler_fmt gem2fmt(u32 flags) { - switch (flags & OMAP_BO_TILED) { + switch (flags & OMAP_BO_TILED_MASK) { case OMAP_BO_TILED_8: return TILFMT_8BIT; case OMAP_BO_TILED_16: diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 2983c003698e..b3e22c890c51 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -11,6 +11,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_file.h> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 6fe14111cd95..24bbe9f2a32e 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -6,6 +6,7 @@ #include <linux/list.h> +#include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_edid.h> diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 1b8b5108caf8..9aeab81dfb90 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -95,7 +95,7 @@ static u32 get_linear_addr(struct drm_framebuffer *fb, bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb) { - return omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED; + return omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED_MASK; } /* Note: DRM rotates counter-clockwise, TILER & DSS rotates clockwise */ @@ -135,7 +135,6 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); const struct drm_format_info *format = omap_fb->format; - struct plane *plane = &omap_fb->planes[0]; u32 x, y, orient = 0; info->fourcc = fb->format->format; @@ -154,7 +153,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, x = state->src_x >> 16; y = state->src_y >> 16; - if (omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED) { + if (omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED_MASK) { u32 w = state->src_w >> 16; u32 h = state->src_h >> 16; @@ -209,10 +208,8 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, info->screen_width /= format->cpp[0]; if (fb->format->format == DRM_FORMAT_NV12) { - plane = &omap_fb->planes[1]; - if (info->rotation_type == OMAP_DSS_ROT_TILER) { - WARN_ON(!(omap_gem_flags(fb->obj[1]) & OMAP_BO_TILED)); + WARN_ON(!(omap_gem_flags(fb->obj[1]) & OMAP_BO_TILED_MASK)); omap_gem_rotated_dma_addr(fb->obj[1], orient, x/2, y/2, &info->p_uv_addr); } else { diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 08f539efddfb..e518d93ca6df 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -67,7 +67,7 @@ struct omap_gem_object { /** * # of users of dma_addr */ - u32 dma_addr_cnt; + refcount_t dma_addr_cnt; /** * If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag @@ -196,7 +196,7 @@ static void omap_gem_evict(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); struct omap_drm_private *priv = obj->dev->dev_private; - if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { enum tiler_fmt fmt = gem2fmt(omap_obj->flags); int i; @@ -324,7 +324,7 @@ size_t omap_gem_mmap_size(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); size_t size = obj->size; - if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { /* for tiled buffers, the virtual size has stride rounded up * to 4kb.. (to hide the fact that row n+1 might start 16kb or * 32kb later!). But we don't back the entire buffer with @@ -513,7 +513,7 @@ vm_fault_t omap_gem_fault(struct vm_fault *vmf) * probably trigger put_pages()? */ - if (omap_obj->flags & OMAP_BO_TILED) + if (omap_obj->flags & OMAP_BO_TILED_MASK) ret = omap_gem_fault_2d(obj, vma, vmf); else ret = omap_gem_fault_1d(obj, vma, vmf); @@ -773,18 +773,20 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) mutex_lock(&omap_obj->lock); if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { - if (omap_obj->dma_addr_cnt == 0) { + if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { u32 npages = obj->size >> PAGE_SHIFT; enum tiler_fmt fmt = gem2fmt(omap_obj->flags); struct tiler_block *block; BUG_ON(omap_obj->block); + refcount_set(&omap_obj->dma_addr_cnt, 1); + ret = omap_gem_attach_pages(obj); if (ret) goto fail; - if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { block = tiler_reserve_2d(fmt, omap_obj->width, omap_obj->height, 0); @@ -813,13 +815,15 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) omap_obj->block = block; DBG("got dma address: %pad", &omap_obj->dma_addr); + } else { + refcount_inc(&omap_obj->dma_addr_cnt); } - omap_obj->dma_addr_cnt++; - - *dma_addr = omap_obj->dma_addr; + if (dma_addr) + *dma_addr = omap_obj->dma_addr; } else if (omap_gem_is_contiguous(omap_obj)) { - *dma_addr = omap_obj->dma_addr; + if (dma_addr) + *dma_addr = omap_obj->dma_addr; } else { ret = -EINVAL; goto fail; @@ -832,38 +836,46 @@ fail: } /** + * omap_gem_unpin_locked() - Unpin a GEM object from memory + * @obj: the GEM object + * + * omap_gem_unpin() without locking. + */ +static void omap_gem_unpin_locked(struct drm_gem_object *obj) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + int ret; + + if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { + ret = tiler_unpin(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not unpin pages: %d\n", ret); + } + ret = tiler_release(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not release unmap: %d\n", ret); + } + omap_obj->dma_addr = 0; + omap_obj->block = NULL; + } +} + +/** * omap_gem_unpin() - Unpin a GEM object from memory * @obj: the GEM object * * Unpin the given GEM object previously pinned with omap_gem_pin(). Pins are - * reference-counted, the actualy unpin will only be performed when the number + * reference-counted, the actual unpin will only be performed when the number * of calls to this function matches the number of calls to omap_gem_pin(). */ void omap_gem_unpin(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); - int ret; mutex_lock(&omap_obj->lock); - - if (omap_obj->dma_addr_cnt > 0) { - omap_obj->dma_addr_cnt--; - if (omap_obj->dma_addr_cnt == 0) { - ret = tiler_unpin(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not unpin pages: %d\n", ret); - } - ret = tiler_release(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not release unmap: %d\n", ret); - } - omap_obj->dma_addr = 0; - omap_obj->block = NULL; - } - } - + omap_gem_unpin_locked(obj); mutex_unlock(&omap_obj->lock); } @@ -879,8 +891,8 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, mutex_lock(&omap_obj->lock); - if ((omap_obj->dma_addr_cnt > 0) && omap_obj->block && - (omap_obj->flags & OMAP_BO_TILED)) { + if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block && + (omap_obj->flags & OMAP_BO_TILED_MASK)) { *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); ret = 0; } @@ -895,7 +907,7 @@ int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient) { struct omap_gem_object *omap_obj = to_omap_bo(obj); int ret = -EINVAL; - if (omap_obj->flags & OMAP_BO_TILED) + if (omap_obj->flags & OMAP_BO_TILED_MASK) ret = tiler_stride(gem2fmt(omap_obj->flags), orient); return ret; } @@ -1030,10 +1042,11 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", omap_obj->flags, obj->name, kref_read(&obj->refcount), - off, &omap_obj->dma_addr, omap_obj->dma_addr_cnt, + off, &omap_obj->dma_addr, + refcount_read(&omap_obj->dma_addr_cnt), omap_obj->vaddr, omap_obj->roll); - if (omap_obj->flags & OMAP_BO_TILED) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height); if (omap_obj->block) { struct tcm_area *area = &omap_obj->block->area; @@ -1093,7 +1106,7 @@ void omap_gem_free_object(struct drm_gem_object *obj) mutex_lock(&omap_obj->lock); /* The object should not be pinned. */ - WARN_ON(omap_obj->dma_addr_cnt > 0); + WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0); if (omap_obj->pages) { if (omap_obj->flags & OMAP_BO_MEM_DMABUF) @@ -1120,6 +1133,38 @@ void omap_gem_free_object(struct drm_gem_object *obj) kfree(omap_obj); } +static bool omap_gem_validate_flags(struct drm_device *dev, u32 flags) +{ + struct omap_drm_private *priv = dev->dev_private; + + switch (flags & OMAP_BO_CACHE_MASK) { + case OMAP_BO_CACHED: + case OMAP_BO_WC: + case OMAP_BO_CACHE_MASK: + break; + + default: + return false; + } + + if (flags & OMAP_BO_TILED_MASK) { + if (!priv->usergart) + return false; + + switch (flags & OMAP_BO_TILED_MASK) { + case OMAP_BO_TILED_8: + case OMAP_BO_TILED_16: + case OMAP_BO_TILED_32: + break; + + default: + return false; + } + } + + return true; +} + /* GEM buffer object constructor */ struct drm_gem_object *omap_gem_new(struct drm_device *dev, union omap_gem_size gsize, u32 flags) @@ -1131,18 +1176,15 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, size_t size; int ret; - /* Validate the flags and compute the memory and cache flags. */ - if (flags & OMAP_BO_TILED) { - if (!priv->usergart) { - dev_err(dev->dev, "Tiled buffers require DMM\n"); - return NULL; - } + if (!omap_gem_validate_flags(dev, flags)) + return NULL; + /* Validate the flags and compute the memory and cache flags. */ + if (flags & OMAP_BO_TILED_MASK) { /* * Tiled buffers are always shmem paged backed. When they are * scanned out, they are remapped into DMM/TILER. */ - flags &= ~OMAP_BO_SCANOUT; flags |= OMAP_BO_MEM_SHMEM; /* @@ -1153,9 +1195,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, flags |= tiler_get_cpu_cache_flags(); } else if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { /* - * OMAP_BO_SCANOUT hints that the buffer doesn't need to be - * tiled. However, to lower the pressure on memory allocation, - * use contiguous memory only if no TILER is available. + * If we don't have DMM, we must allocate scanout buffers + * from contiguous DMA memory. */ flags |= OMAP_BO_MEM_DMA_API; } else if (!(flags & OMAP_BO_MEM_DMABUF)) { @@ -1174,7 +1215,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, omap_obj->flags = flags; mutex_init(&omap_obj->lock); - if (flags & OMAP_BO_TILED) { + if (flags & OMAP_BO_TILED_MASK) { /* * For tiled buffers align dimensions to slot boundaries and * calculate size based on aligned dimensions. diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index e8c3ae7ac77e..7344bb61936c 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -67,7 +67,7 @@ static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, { struct drm_gem_object *obj = buffer->priv; struct page **pages; - if (omap_gem_flags(obj) & OMAP_BO_TILED) { + if (omap_gem_flags(obj) & OMAP_BO_TILED_MASK) { /* TODO we would need to pin at least part of the buffer to * get de-tiled view. For now just reject it. */ |