diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-07-17 15:37:56 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-07-17 15:37:57 +0200 |
commit | 6c7f27441d6af776a89147027c6f4a11c0162c64 (patch) | |
tree | fc6f19c0b243dd77de3f270e1c2e8a41be086531 /drivers/gpu/drm/bridge | |
parent | fdf0eaf11452d72945af31804e2a1048ee1b574c (diff) | |
parent | 36672dda2eb715af99e9abbcdc400d46598b691c (diff) | |
download | linux-stable-6c7f27441d6af776a89147027c6f4a11c0162c64.tar.gz linux-stable-6c7f27441d6af776a89147027c6f4a11c0162c64.tar.bz2 linux-stable-6c7f27441d6af776a89147027c6f4a11c0162c64.zip |
Merge tag 'drm-misc-next-2023-07-13' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v6.6:
UAPI Changes:
* fbdev:
* Make fbdev userspace interfaces optional; only leaves the
framebuffer console active
* prime:
* Support dma-buf self-import for all drivers automatically: improves
support for many userspace compositors
Cross-subsystem Changes:
* backlight:
* Fix interaction with fbdev in several drivers
* base: Convert struct platform.remove to return void; part of a larger,
tree-wide effort
* dma-buf: Acquire reservation lock for mmap() in exporters; part
of an on-going effort to simplify locking around dma-bufs
* fbdev:
* Use Linux device instead of fbdev device in many places
* Use deferred-I/O helper macros in various drivers
* i2c: Convert struct i2c from .probe_new to .probe; part of a larger,
tree-wide effort
* video:
* Avoid including <linux/screen_info.h>
Core Changes:
* atomic:
* Improve logging
* prime:
* Remove struct drm_driver.gem_prime_mmap plus driver updates: all
drivers now implement this callback with drm_gem_prime_mmap()
* gem:
* Support execution contexts: provides locking over multiple GEM
objects
* ttm:
* Support init_on_free
* Swapout fixes
Driver Changes:
* accel:
* ivpu: MMU updates; Support debugfs
* ast:
* Improve device-model detection
* Cleanups
* bridge:
* dw-hdmi: Improve support for YUV420 bus format
* dw-mipi-dsi: Fix enable/disable of DSI controller
* lt9611uxc: Use MODULE_FIRMWARE()
* ps8640: Remove broken EDID code
* samsung-dsim: Fix command transfer
* tc358764: Handle HS/VS polarity; Use BIT() macro; Various cleanups
* Cleanups
* ingenic:
* Kconfig REGMAP fixes
* loongson:
* Support display controller
* mgag200:
* Minor fixes
* mxsfb:
* Support disabling overlay planes
* nouveau:
* Improve VRAM detection
* Various fixes and cleanups
* panel:
* panel-edp: Support AUO B116XAB01.4
* Support Visionox R66451 plus DT bindings
* Cleanups
* ssd130x:
* Support per-controller default resolution plus DT bindings
* Reduce memory-allocation overhead
* Cleanups
* tidss:
* Support TI AM625 plus DT bindings
* Implement new connector model plus driver updates
* vkms
* Improve write-back support
* Documentation fixes
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230713090830.GA23281@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/bridge')
-rw-r--r-- | drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 77 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/parade-ps8640.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/samsung-dsim.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/sii902x.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/tc358762.c | 63 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/tc358764.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/tc358767.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/bridge/ti-tfp410.c | 43 |
14 files changed, 241 insertions, 184 deletions
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index f6822dfa3805..ecb935e46b62 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -54,6 +54,26 @@ #include "cdns-mhdp8546-hdcp.h" #include "cdns-mhdp8546-j721e.h" +static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + /* Enable SW event interrupts */ + if (mhdp->bridge_attached) + writel(readl(mhdp->regs + CDNS_APB_INT_MASK) & + ~CDNS_APB_INT_MASK_SW_EVENT_INT, + mhdp->regs + CDNS_APB_INT_MASK); +} + +static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + writel(readl(mhdp->regs + CDNS_APB_INT_MASK) | + CDNS_APB_INT_MASK_SW_EVENT_INT, + mhdp->regs + CDNS_APB_INT_MASK); +} + static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) { int ret, empty; @@ -749,9 +769,7 @@ static int cdns_mhdp_fw_activate(const struct firmware *fw, * MHDP_HW_STOPPED happens only due to driver removal when * bridge should already be detached. */ - if (mhdp->bridge_attached) - writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, - mhdp->regs + CDNS_APB_INT_MASK); + cdns_mhdp_bridge_hpd_enable(&mhdp->bridge); spin_unlock(&mhdp->start_lock); @@ -1740,8 +1758,7 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge, /* Enable SW event interrupts */ if (hw_ready) - writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, - mhdp->regs + CDNS_APB_INT_MASK); + cdns_mhdp_bridge_hpd_enable(bridge); return 0; aux_unregister: @@ -2146,6 +2163,27 @@ cdns_mhdp_bridge_atomic_reset(struct drm_bridge *bridge) return &cdns_mhdp_state->base; } +static u32 *cdns_mhdp_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + *num_input_fmts = 1; + input_fmts[0] = MEDIA_BUS_FMT_RGB121212_1X36; + + return input_fmts; +} + static int cdns_mhdp_atomic_check(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, @@ -2165,6 +2203,13 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge, return -EINVAL; } + /* + * There might be flags negotiation supported in future. + * Set the bus flags in atomic_check statically for now. + */ + if (mhdp->info) + bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags; + mutex_unlock(&mhdp->link_mutex); return 0; } @@ -2184,23 +2229,6 @@ static struct edid *cdns_mhdp_bridge_get_edid(struct drm_bridge *bridge, return cdns_mhdp_get_edid(mhdp, connector); } -static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge) -{ - struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); - - /* Enable SW event interrupts */ - if (mhdp->bridge_attached) - writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, - mhdp->regs + CDNS_APB_INT_MASK); -} - -static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge) -{ - struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); - - writel(CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK); -} - static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = { .atomic_enable = cdns_mhdp_atomic_enable, .atomic_disable = cdns_mhdp_atomic_disable, @@ -2210,6 +2238,7 @@ static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = { .atomic_duplicate_state = cdns_mhdp_bridge_atomic_duplicate_state, .atomic_destroy_state = cdns_mhdp_bridge_atomic_destroy_state, .atomic_reset = cdns_mhdp_bridge_atomic_reset, + .atomic_get_input_bus_fmts = cdns_mhdp_get_input_bus_fmts, .detect = cdns_mhdp_bridge_detect, .get_edid = cdns_mhdp_bridge_get_edid, .hpd_enable = cdns_mhdp_bridge_hpd_enable, @@ -2529,8 +2558,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev) mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; - if (mhdp->info) - mhdp->bridge.timings = mhdp->info->timings; ret = phy_init(mhdp->phy); if (ret) { @@ -2617,7 +2644,7 @@ static const struct of_device_id mhdp_ids[] = { #ifdef CONFIG_DRM_CDNS_MHDP8546_J721E { .compatible = "ti,j721e-mhdp8546", .data = &(const struct cdns_mhdp_platform_info) { - .timings = &mhdp_ti_j721e_bridge_timings, + .input_bus_flags = &mhdp_ti_j721e_bridge_input_bus_flags, .ops = &mhdp_ti_j721e_ops, }, }, diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h index bedddd510d17..bad2fc0c7306 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h @@ -336,7 +336,7 @@ struct cdns_mhdp_bridge_state { }; struct cdns_mhdp_platform_info { - const struct drm_bridge_timings *timings; + const u32 *input_bus_flags; const struct mhdp_platform_ops *ops; }; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c index dfe1b59514f7..12d04be4e242 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c @@ -71,8 +71,7 @@ const struct mhdp_platform_ops mhdp_ti_j721e_ops = { .disable = cdns_mhdp_j721e_disable, }; -const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings = { - .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | - DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE | - DRM_BUS_FLAG_DE_HIGH, -}; +const u32 +mhdp_ti_j721e_bridge_input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_DE_HIGH; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h index 97d20d115a24..5ddca07a4255 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h @@ -14,6 +14,6 @@ struct mhdp_platform_ops; extern const struct mhdp_platform_ops mhdp_ti_j721e_ops; -extern const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings; +extern const u32 mhdp_ti_j721e_bridge_input_bus_flags; #endif /* !CDNS_MHDP8546_J721E_H */ diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 2a57e804ea02..22c84d29c2bc 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -28,6 +28,8 @@ #define EDID_BLOCK_SIZE 128 #define EDID_NUM_BLOCKS 2 +#define FW_FILE "lt9611uxc_fw.bin" + struct lt9611uxc { struct device *dev; struct drm_bridge bridge; @@ -754,7 +756,7 @@ static int lt9611uxc_firmware_update(struct lt9611uxc *lt9611uxc) REG_SEQ0(0x805a, 0x00), }; - ret = request_firmware(&fw, "lt9611uxc_fw.bin", lt9611uxc->dev); + ret = request_firmware(&fw, FW_FILE, lt9611uxc->dev); if (ret < 0) return ret; @@ -1019,3 +1021,5 @@ module_i2c_driver(lt9611uxc_driver); MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>"); MODULE_LICENSE("GPL v2"); + +MODULE_FIRMWARE(FW_FILE); diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 8801cdd033b5..8161b1a1a4b1 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -105,7 +105,6 @@ struct ps8640 { struct gpio_desc *gpio_reset; struct gpio_desc *gpio_powerdown; struct device_link *link; - struct edid *edid; bool pre_enabled; bool need_post_hpd_delay; }; @@ -155,23 +154,6 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) return container_of(aux, struct ps8640, aux); } -static bool ps8640_of_panel_on_aux_bus(struct device *dev) -{ - struct device_node *bus, *panel; - - bus = of_get_child_by_name(dev->of_node, "aux-bus"); - if (!bus) - return false; - - panel = of_get_child_by_name(bus, "panel"); - of_node_put(bus); - if (!panel) - return false; - of_node_put(panel); - - return true; -} - static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wait_us) { struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; @@ -539,50 +521,6 @@ static void ps8640_bridge_detach(struct drm_bridge *bridge) device_link_del(ps_bridge->link); } -static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) -{ - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); - struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; - bool poweroff = !ps_bridge->pre_enabled; - - if (!ps_bridge->edid) { - /* - * When we end calling get_edid() triggered by an ioctl, i.e - * - * drm_mode_getconnector (ioctl) - * -> drm_helper_probe_single_connector_modes - * -> drm_bridge_connector_get_modes - * -> ps8640_bridge_get_edid - * - * We need to make sure that what we need is enabled before - * reading EDID, for this chip, we need to do a full poweron, - * otherwise it will fail. - */ - if (poweroff) - drm_atomic_bridge_chain_pre_enable(bridge, - connector->state->state); - - ps_bridge->edid = drm_get_edid(connector, - ps_bridge->page[PAGE0_DP_CNTL]->adapter); - - /* - * If we call the get_edid() function without having enabled the - * chip before, return the chip to its original power state. - */ - if (poweroff) - drm_atomic_bridge_chain_post_disable(bridge, - connector->state->state); - } - - if (!ps_bridge->edid) { - dev_err(dev, "Failed to get EDID\n"); - return NULL; - } - - return drm_edid_duplicate(ps_bridge->edid); -} - static void ps8640_runtime_disable(void *data) { pm_runtime_dont_use_autosuspend(data); @@ -592,7 +530,6 @@ static void ps8640_runtime_disable(void *data) static const struct drm_bridge_funcs ps8640_bridge_funcs = { .attach = ps8640_bridge_attach, .detach = ps8640_bridge_detach, - .get_edid = ps8640_bridge_get_edid, .atomic_post_disable = ps8640_atomic_post_disable, .atomic_pre_enable = ps8640_atomic_pre_enable, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, @@ -706,14 +643,6 @@ static int ps8640_probe(struct i2c_client *client) ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP; /* - * In the device tree, if panel is listed under aux-bus of the bridge - * node, panel driver should be able to retrieve EDID by itself using - * aux-bus. So let's not set DRM_BRIDGE_OP_EDID here. - */ - if (!ps8640_of_panel_on_aux_bus(&client->dev)) - ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; - - /* * Get MIPI DSI resources early. These can return -EPROBE_DEFER so * we want to get them out of the way sooner. */ @@ -777,13 +706,6 @@ static int ps8640_probe(struct i2c_client *client) return ret; } -static void ps8640_remove(struct i2c_client *client) -{ - struct ps8640 *ps_bridge = i2c_get_clientdata(client); - - kfree(ps_bridge->edid); -} - static const struct of_device_id ps8640_match[] = { { .compatible = "parade,ps8640" }, { } @@ -792,7 +714,6 @@ MODULE_DEVICE_TABLE(of, ps8640_match); static struct i2c_driver ps8640_driver = { .probe = ps8640_probe, - .remove = ps8640_remove, .driver = { .name = "ps8640", .of_match_table = ps8640_match, diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 043b8109e64a..9b7a00bafeaa 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1009,7 +1009,7 @@ static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi) do { u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG); - if (!(reg & DSIM_SFR_HEADER_FULL)) + if (reg & DSIM_SFR_HEADER_EMPTY) return 0; if (!cond_resched()) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index aac239729a1d..2bdc5b439beb 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -473,6 +473,41 @@ static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge, return sii902x_get_edid(sii902x, connector); } +static u32 *sii902x_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + *num_input_fmts = 1; + + return input_fmts; +} + +static int sii902x_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + /* + * There might be flags negotiation supported in future but + * set the bus flags in atomic_check statically for now. + */ + bridge_state->input_bus_cfg.flags = bridge->timings->input_bus_flags; + + return 0; +} + static const struct drm_bridge_funcs sii902x_bridge_funcs = { .attach = sii902x_bridge_attach, .mode_set = sii902x_bridge_mode_set, @@ -480,6 +515,11 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = { .enable = sii902x_bridge_enable, .detect = sii902x_bridge_detect, .get_edid = sii902x_bridge_get_edid, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts, + .atomic_check = sii902x_bridge_atomic_check, }; static int sii902x_mute(struct sii902x *sii902x, bool mute) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 7b66f362afd8..9a3db5234a0e 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -49,20 +49,6 @@ #define HDMI14_MAX_TMDSCLK 340000000 -enum hdmi_datamap { - RGB444_8B = 0x01, - RGB444_10B = 0x03, - RGB444_12B = 0x05, - RGB444_16B = 0x07, - YCbCr444_8B = 0x09, - YCbCr444_10B = 0x0B, - YCbCr444_12B = 0x0D, - YCbCr444_16B = 0x0F, - YCbCr422_8B = 0x16, - YCbCr422_10B = 0x14, - YCbCr422_12B = 0x12, -}; - static const u16 csc_coeff_default[3][4] = { { 0x2000, 0x0000, 0x0000, 0x0000 }, { 0x0000, 0x2000, 0x0000, 0x0000 }, @@ -856,10 +842,10 @@ static void dw_hdmi_gp_audio_enable(struct dw_hdmi *hdmi) if (pdata->enable_audio) pdata->enable_audio(hdmi, - hdmi->channels, - hdmi->sample_width, - hdmi->sample_rate, - hdmi->sample_non_pcm); + hdmi->channels, + hdmi->sample_width, + hdmi->sample_rate, + hdmi->sample_non_pcm); } static void dw_hdmi_gp_audio_disable(struct dw_hdmi *hdmi) @@ -2710,9 +2696,10 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, /* Default 8bit fallback */ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; - *num_output_fmts = i; - - return output_fmts; + if (drm_mode_is_420_only(info, mode)) { + *num_output_fmts = i; + return output_fmts; + } } /* @@ -3346,6 +3333,12 @@ static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi) return 0; } +bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi) +{ + return hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format); +} +EXPORT_SYMBOL_GPL(dw_hdmi_bus_fmt_is_420); + struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, const struct dw_hdmi_plat_data *plat_data) { diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index b2efecf7d160..4291798bd70f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -265,6 +265,7 @@ struct dw_mipi_dsi { struct dw_mipi_dsi *master; /* dual-dsi master ptr */ struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */ + struct drm_display_mode mode; const struct dw_mipi_dsi_plat_data *plat_data; }; @@ -332,6 +333,7 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, if (IS_ERR(bridge)) return PTR_ERR(bridge); + bridge->pre_enable_prev_first = true; dsi->panel_bridge = bridge; drm_bridge_add(&dsi->bridge); @@ -859,15 +861,6 @@ static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge, */ dw_mipi_dsi_set_mode(dsi, 0); - /* - * TODO Only way found to call panel-bridge post_disable & - * panel unprepare before the dsi "final" disable... - * This needs to be fixed in the drm_bridge framework and the API - * needs to be updated to manage our own call chains... - */ - if (dsi->panel_bridge->funcs->post_disable) - dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge); - if (phy_ops->power_off) phy_ops->power_off(dsi->plat_data->priv_data); @@ -942,15 +935,25 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi, phy_ops->power_on(dsi->plat_data->priv_data); } +static void dw_mipi_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); + + /* Power up the dsi ctl into a command mode */ + dw_mipi_dsi_mode_set(dsi, &dsi->mode); + if (dsi->slave) + dw_mipi_dsi_mode_set(dsi->slave, &dsi->mode); +} + static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode) { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); - dw_mipi_dsi_mode_set(dsi, adjusted_mode); - if (dsi->slave) - dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode); + /* Store the display mode for later use in pre_enable callback */ + drm_mode_copy(&dsi->mode, adjusted_mode); } static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge, @@ -1004,6 +1007,7 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_pre_enable = dw_mipi_dsi_bridge_atomic_pre_enable, .atomic_enable = dw_mipi_dsi_bridge_atomic_enable, .atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable, .mode_set = dw_mipi_dsi_bridge_mode_set, diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 5641395fd310..46198af9eebb 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -41,8 +41,17 @@ #define DSI_LANEENABLE 0x0210 /* Enables each lane */ #define DSI_RX_START 1 -/* LCDC/DPI Host Registers */ -#define LCDCTRL 0x0420 +/* LCDC/DPI Host Registers, based on guesswork that this matches TC358764 */ +#define LCDCTRL 0x0420 /* Video Path Control */ +#define LCDCTRL_MSF BIT(0) /* Magic square in RGB666 */ +#define LCDCTRL_VTGEN BIT(4)/* Use chip clock for timing */ +#define LCDCTRL_UNK6 BIT(6) /* Unknown */ +#define LCDCTRL_EVTMODE BIT(5) /* Event mode */ +#define LCDCTRL_RGB888 BIT(8) /* RGB888 mode */ +#define LCDCTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */ +#define LCDCTRL_DEPOL BIT(18) /* Polarity of DE signal */ +#define LCDCTRL_VSPOL BIT(19) /* Polarity of VSYNC signal */ +#define LCDCTRL_VSDELAY(v) (((v) & 0xfff) << 20) /* VSYNC delay */ /* SPI Master Registers */ #define SPICMR 0x0450 @@ -65,6 +74,7 @@ struct tc358762 { struct regulator *regulator; struct drm_bridge *panel_bridge; struct gpio_desc *reset_gpio; + struct drm_display_mode mode; bool pre_enabled; int error; }; @@ -105,6 +115,8 @@ static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge) static int tc358762_init(struct tc358762 *ctx) { + u32 lcdctrl; + tc358762_write(ctx, DSI_LANEENABLE, LANEENABLE_L0EN | LANEENABLE_CLEN); tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5); @@ -114,7 +126,18 @@ static int tc358762_init(struct tc358762 *ctx) tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD); tc358762_write(ctx, SPICMR, 0x00); - tc358762_write(ctx, LCDCTRL, 0x00100150); + + lcdctrl = LCDCTRL_VSDELAY(1) | LCDCTRL_RGB888 | + LCDCTRL_UNK6 | LCDCTRL_VTGEN; + + if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC) + lcdctrl |= LCDCTRL_HSPOL; + + if (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC) + lcdctrl |= LCDCTRL_VSPOL; + + tc358762_write(ctx, LCDCTRL, lcdctrl); + tc358762_write(ctx, SYSCTRL, 0x040f); msleep(100); @@ -126,7 +149,7 @@ static int tc358762_init(struct tc358762 *ctx) return tc358762_clear_error(ctx); } -static void tc358762_post_disable(struct drm_bridge *bridge) +static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_state *state) { struct tc358762 *ctx = bridge_to_tc358762(bridge); int ret; @@ -148,7 +171,7 @@ static void tc358762_post_disable(struct drm_bridge *bridge) dev_err(ctx->dev, "error disabling regulators (%d)\n", ret); } -static void tc358762_pre_enable(struct drm_bridge *bridge) +static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *state) { struct tc358762 *ctx = bridge_to_tc358762(bridge); int ret; @@ -162,11 +185,17 @@ static void tc358762_pre_enable(struct drm_bridge *bridge) usleep_range(5000, 10000); } + ctx->pre_enabled = true; +} + +static void tc358762_enable(struct drm_bridge *bridge, struct drm_bridge_state *state) +{ + struct tc358762 *ctx = bridge_to_tc358762(bridge); + int ret; + ret = tc358762_init(ctx); if (ret < 0) dev_err(ctx->dev, "error initializing bridge (%d)\n", ret); - - ctx->pre_enabled = true; } static int tc358762_attach(struct drm_bridge *bridge, @@ -178,10 +207,24 @@ static int tc358762_attach(struct drm_bridge *bridge, bridge, flags); } +static void tc358762_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adj) +{ + struct tc358762 *ctx = bridge_to_tc358762(bridge); + + drm_mode_copy(&ctx->mode, mode); +} + static const struct drm_bridge_funcs tc358762_bridge_funcs = { - .post_disable = tc358762_post_disable, - .pre_enable = tc358762_pre_enable, + .atomic_post_disable = tc358762_post_disable, + .atomic_pre_enable = tc358762_pre_enable, + .atomic_enable = tc358762_enable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, .attach = tc358762_attach, + .mode_set = tc358762_bridge_mode_set, }; static int tc358762_parse_dt(struct tc358762 *ctx) @@ -231,7 +274,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) dsi->lanes = 1; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_LPM; + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_HSE; ret = tc358762_parse_dt(ctx); if (ret < 0) diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index f85654f1b104..deccb3995022 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -42,10 +42,10 @@ /* Video path registers */ #define VP_CTRL 0x0450 /* Video Path Control */ -#define VP_CTRL_MSF(v) FLD_VAL(v, 0, 0) /* Magic square in RGB666 */ -#define VP_CTRL_VTGEN(v) FLD_VAL(v, 4, 4) /* Use chip clock for timing */ -#define VP_CTRL_EVTMODE(v) FLD_VAL(v, 5, 5) /* Event mode */ -#define VP_CTRL_RGB888(v) FLD_VAL(v, 8, 8) /* RGB888 mode */ +#define VP_CTRL_MSF BIT(0) /* Magic square in RGB666 */ +#define VP_CTRL_VTGEN BIT(4) /* Use chip clock for timing */ +#define VP_CTRL_EVTMODE BIT(5) /* Event mode */ +#define VP_CTRL_RGB888 BIT(8) /* RGB888 mode */ #define VP_CTRL_VSDELAY(v) FLD_VAL(v, 31, 20) /* VSYNC delay */ #define VP_CTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */ #define VP_CTRL_DEPOL BIT(18) /* Polarity of DE signal */ @@ -176,7 +176,7 @@ static void tc358764_read(struct tc358764 *ctx, u16 addr, u32 *val) if (ret >= 0) le32_to_cpus(val); - dev_dbg(ctx->dev, "read: %d, addr: %d\n", addr, *val); + dev_dbg(ctx->dev, "read: addr=0x%04x data=0x%08x\n", addr, *val); } static void tc358764_write(struct tc358764 *ctx, u16 addr, u32 val) @@ -233,8 +233,8 @@ static int tc358764_init(struct tc358764 *ctx) tc358764_write(ctx, DSI_STARTDSI, DSI_RX_START); /* configure video path */ - tc358764_write(ctx, VP_CTRL, VP_CTRL_VSDELAY(15) | VP_CTRL_RGB888(1) | - VP_CTRL_EVTMODE(1) | VP_CTRL_HSPOL | VP_CTRL_VSPOL); + tc358764_write(ctx, VP_CTRL, VP_CTRL_VSDELAY(15) | VP_CTRL_RGB888 | + VP_CTRL_EVTMODE | VP_CTRL_HSPOL | VP_CTRL_VSPOL); /* reset PHY */ tc358764_write(ctx, LV_PHY0, LV_PHY0_RST(1) | diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 65dc842e31f0..eaa7edb080fa 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -2215,13 +2215,6 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc) return -EINVAL; } -static void tc_clk_disable(void *data) -{ - struct clk *refclk = data; - - clk_disable_unprepare(refclk); -} - static int tc_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -2238,20 +2231,10 @@ static int tc_probe(struct i2c_client *client) if (ret) return ret; - tc->refclk = devm_clk_get(dev, "ref"); - if (IS_ERR(tc->refclk)) { - ret = PTR_ERR(tc->refclk); - dev_err(dev, "Failed to get refclk: %d\n", ret); - return ret; - } - - ret = clk_prepare_enable(tc->refclk); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, tc_clk_disable, tc->refclk); - if (ret) - return ret; + tc->refclk = devm_clk_get_enabled(dev, "ref"); + if (IS_ERR(tc->refclk)) + return dev_err_probe(dev, PTR_ERR(tc->refclk), + "Failed to get and enable the ref clk\n"); /* tRSTW = 100 cycles , at 13 MHz that is ~7.69 us */ usleep_range(10, 15); diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index c06390da9ffd..22b07260a78e 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -206,12 +206,55 @@ static enum drm_mode_status tfp410_mode_valid(struct drm_bridge *bridge, return MODE_OK; } +static u32 *tfp410_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + + *num_input_fmts = 1; + input_fmts[0] = dvi->bus_format; + + return input_fmts; +} + +static int tfp410_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); + + /* + * There might be flags negotiation supported in future. + * Set the bus flags in atomic_check statically for now. + */ + bridge_state->input_bus_cfg.flags = dvi->timings.input_bus_flags; + + return 0; +} + static const struct drm_bridge_funcs tfp410_bridge_funcs = { .attach = tfp410_attach, .detach = tfp410_detach, .enable = tfp410_enable, .disable = tfp410_disable, .mode_valid = tfp410_mode_valid, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_get_input_bus_fmts = tfp410_get_input_bus_fmts, + .atomic_check = tfp410_atomic_check, }; static const struct drm_bridge_timings tfp410_default_timings = { |