diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-02 01:24:20 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-02 01:24:20 +0300 |
commit | f365ab31efacb70bed1e821f7435626e0b2528a6 (patch) | |
tree | e1374b2896d50e652c1e434d70e834d0788aae3a /drivers/gpu/drm/omapdrm/dss/sdi.c | |
parent | 4646de87d32526ee87b46c2e0130413367fb5362 (diff) | |
parent | 59e7a8cc2dcf335116d500d684bfb34d1d97a6fe (diff) | |
download | linux-f365ab31efacb70bed1e821f7435626e0b2528a6.tar.xz |
Merge tag 'drm-next-2020-04-01' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 5.7-rc1.
Highlights:
- i915 enables Tigerlake by default
- i915 and amdgpu have initial OLED backlight support
[ Jani Nikula pipes up and points out that we've had a bunch of
"initial support" code for a long time already, but only now
Lyude made it actually work on real world machines ]
- vmwgfx add support to enable OpenGL 4 userspace
- zero length arrays are mostly removed.
Detailed summary:
new driver:
- tidss: TI Keystone platform display subsystem
core:
- new drm device warn macros
- mode config valid for memory constrained devices
- bridge bus format negotation
- consolidated fake vblank event handling
- dma_alloc related cleanups
- drop get_crtc callback
- dp: DP1.4 EDID corruption test
- EDID CEA detailed timings improvements
- relicense some code to dual GPL2/MIT
- convert core vblank support to per-crtc support
- rework drm_global_mutex
- bridge rework to allow omap_dss custom driver removeal
- remove drm_fb_helper connector interrfaces
- zero-length array removal
scheduler:
- support for modifying the sched list
- revert job distribution optimization
- helper to pick least loaded scheduler
- race condition fix
mst:
- various fixes
- remove register_connector callback
i915:
- uapi to allows userspace specific CS ring buffer sizes
- Tigerlake enablement patches + Tigerlake enabled by default
- new sysfs entries for engine properties
- display/logging refactors
- eDP/DP fixes for DPCD
- Gen7 back to aliasing-ppgtt
- Gen8+ irq refactor
- Avoid globals
- GEM locking fixes and simplifications
- Ice Lake and Elkhart Lake fixes and workarounds
- Baytrail/Haswell instability fix
- GVT - VFIO edid better support
amdgpu:
- Rework VM update handling in preparation for HMM support
- drm load/unload removal fixups
- USB-C PD firmware updates
- HDCP srm support
- Navi/renoir PM watermark fixes
- OLED panel support
- Optimize debugging vram access
- Use BACO for runtime pm
- DC clock programming optimizations and fixes
- PSP fw loading sequence updates
- Drop DRIVER_USE_AGP
- Remove legacy drm load and unload callbacks
- ACP Kconfig fix
- Lots of fixes across the driver
amdkfd:
- runtime pm support
- more gfx config details in amdgpu
radeon:
- drop DRIVER_USE_AGP
vmwgfx:
- Disable DMA when SEV encryption in use
- Shader Model 5 support - needed for GL4 support
msm:
- DPU resource manager refactor
- dpu using atomic global state
mediatek:
- MT8183 DPI support
etnaviv:
- out-of-bounds read fix
- expose feature flags for GC400 STM32MP1 SoC
- runtime suspend entry fix
- dma32 zone fix
hisilicon:
- mode selection fixes
meson:
- YUV420 support
lima:
- add support for heap buffers
tinydrm:
- removal of owner field
- explicit DT dependency removal
- YAML schema conversion
tegra:
- misc cleanups
tidss:
- new driver
virtio:
- better batching of notifications to host
- memory handling reworked
- shmem + gpu context fixes
hibmc:
- add gamma_set support
- improve DPMS support
pl111:
- Integrator IM-PD1 support
sun4i:
- LVDS support for A20 + A33
- DSI panel handling improvements"
* tag 'drm-next-2020-04-01' of git://anongit.freedesktop.org/drm/drm: (1537 commits)
drm/i915/display: Fix mode private_flags comparison at atomic_check
drm/i915/gt: Stage the transfer of the virtual breadcrumb
drm/i915/gt: Select the deepest available parking mode for rc6
drm/i915: Avoid live-lock with i915_vma_parked()
drm/i915/gt: Treat idling as a RPS downclock event
drm/i915/gt: Cancel a hung context if already closed
drm/i915: Use explicit flag to mark unreachable intel_context
drm/amdgpu: don't try to reserve training bo for sriov (v2)
drm/amdgpu/smu11: add support for SMU AC/DC interrupts
drm/amdgpu/swSMU: handle manual AC/DC notifications
drm/amdgpu/swSMU: handle DC controlled by GPIO for navi1x
drm/amdgpu/swSMU: set AC/DC mode based on the current system state (v2)
drm/amdgpu/swSMU: correct the bootup power source for Navi1X (v2)
drm/amdgpu/swSMU: use the smu11 power source helper for navi1x
drm/amdgpu/smu11: add a helper to set the power source
drm/amd/swSMU: add callback to set AC/DC power source (v2)
drm/scheduler: fix rare NULL ptr race
drm/amdgpu: fix the coverage issue to clear ArcVPGRs
drm/amd/display: Fix pageflip event race condition for DCN.
drm/[radeon|amdgpu]: Remove HAINAN board from max_sclk override check
...
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/sdi.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/sdi.c | 178 |
1 files changed, 114 insertions, 64 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index 3b447c01fa2a..417a8740ad0a 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -6,17 +6,19 @@ #define DSS_SUBSYS_NAME "SDI" -#include <linux/kernel.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/regulator/consumer.h> #include <linux/export.h> +#include <linux/kernel.h> +#include <linux/of.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/string.h> -#include <linux/of.h> -#include "omapdss.h" +#include <drm/drm_bridge.h> + #include "dss.h" +#include "omapdss.h" struct sdi_device { struct platform_device *pdev; @@ -30,9 +32,11 @@ struct sdi_device { int datapairs; struct omap_dss_device output; + struct drm_bridge bridge; }; -#define dssdev_to_sdi(dssdev) container_of(dssdev, struct sdi_device, output) +#define drm_bridge_to_sdi(bridge) \ + container_of(bridge, struct sdi_device, bridge) struct sdi_clk_calc_ctx { struct sdi_device *sdi; @@ -118,9 +122,82 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi) dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config); } -static void sdi_display_enable(struct omap_dss_device *dssdev) +/* ----------------------------------------------------------------------------- + * DRM Bridge Operations + */ + +static int sdi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + return drm_bridge_attach(bridge->encoder, sdi->output.next_bridge, + bridge, flags); +} + +static enum drm_mode_status +sdi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode) +{ + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); + unsigned long pixelclock = mode->clock * 1000; + struct dispc_clock_info dispc_cinfo; + unsigned long fck; + int ret; + + if (pixelclock == 0) + return MODE_NOCLOCK; + + ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo); + if (ret < 0) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + +static bool sdi_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); + unsigned long pixelclock = mode->clock * 1000; + struct dispc_clock_info dispc_cinfo; + unsigned long fck; + unsigned long pck; + int ret; + + ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo); + if (ret < 0) + return false; + + pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div; + + if (pck != pixelclock) + dev_dbg(&sdi->pdev->dev, + "pixel clock adjusted from %lu Hz to %lu Hz\n", + pixelclock, pck); + + adjusted_mode->clock = pck / 1000; + + return true; +} + +static void sdi_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); + + sdi->pixelclock = adjusted_mode->clock * 1000; +} + +static void sdi_bridge_enable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { - struct sdi_device *sdi = dssdev_to_sdi(dssdev); + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); struct dispc_clock_info dispc_cinfo; unsigned long fck; int r; @@ -181,9 +258,10 @@ err_get_dispc: regulator_disable(sdi->vdds_sdi_reg); } -static void sdi_display_disable(struct omap_dss_device *dssdev) +static void sdi_bridge_disable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { - struct sdi_device *sdi = dssdev_to_sdi(dssdev); + struct sdi_device *sdi = drm_bridge_to_sdi(bridge); dss_mgr_disable(&sdi->output); @@ -194,86 +272,56 @@ static void sdi_display_disable(struct omap_dss_device *dssdev) regulator_disable(sdi->vdds_sdi_reg); } -static void sdi_set_timings(struct omap_dss_device *dssdev, - const struct drm_display_mode *mode) -{ - struct sdi_device *sdi = dssdev_to_sdi(dssdev); - - sdi->pixelclock = mode->clock * 1000; -} +static const struct drm_bridge_funcs sdi_bridge_funcs = { + .attach = sdi_bridge_attach, + .mode_valid = sdi_bridge_mode_valid, + .mode_fixup = sdi_bridge_mode_fixup, + .mode_set = sdi_bridge_mode_set, + .atomic_enable = sdi_bridge_enable, + .atomic_disable = sdi_bridge_disable, +}; -static int sdi_check_timings(struct omap_dss_device *dssdev, - struct drm_display_mode *mode) +static void sdi_bridge_init(struct sdi_device *sdi) { - struct sdi_device *sdi = dssdev_to_sdi(dssdev); - struct dispc_clock_info dispc_cinfo; - unsigned long pixelclock = mode->clock * 1000; - unsigned long fck; - unsigned long pck; - int r; + sdi->bridge.funcs = &sdi_bridge_funcs; + sdi->bridge.of_node = sdi->pdev->dev.of_node; + sdi->bridge.type = DRM_MODE_CONNECTOR_LVDS; - if (pixelclock == 0) - return -EINVAL; - - r = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo); - if (r) - return r; - - pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div; - - if (pck != pixelclock) { - DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n", - pixelclock, pck); - - mode->clock = pck / 1000; - } - - return 0; + drm_bridge_add(&sdi->bridge); } -static int sdi_connect(struct omap_dss_device *src, - struct omap_dss_device *dst) +static void sdi_bridge_cleanup(struct sdi_device *sdi) { - return omapdss_device_connect(dst->dss, dst, dst->next); + drm_bridge_remove(&sdi->bridge); } -static void sdi_disconnect(struct omap_dss_device *src, - struct omap_dss_device *dst) -{ - omapdss_device_disconnect(dst, dst->next); -} - -static const struct omap_dss_device_ops sdi_ops = { - .connect = sdi_connect, - .disconnect = sdi_disconnect, - - .enable = sdi_display_enable, - .disable = sdi_display_disable, - - .check_timings = sdi_check_timings, - .set_timings = sdi_set_timings, -}; +/* ----------------------------------------------------------------------------- + * Initialisation and Cleanup + */ static int sdi_init_output(struct sdi_device *sdi) { struct omap_dss_device *out = &sdi->output; int r; + sdi_bridge_init(sdi); + out->dev = &sdi->pdev->dev; out->id = OMAP_DSS_OUTPUT_SDI; out->type = OMAP_DISPLAY_TYPE_SDI; out->name = "sdi.0"; out->dispc_channel = OMAP_DSS_CHANNEL_LCD; /* We have SDI only on OMAP3, where it's on port 1 */ - out->of_ports = BIT(1); - out->ops = &sdi_ops; + out->of_port = 1; out->owner = THIS_MODULE; out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE /* 15.5.9.1.2 */ | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE; - r = omapdss_device_init_output(out); - if (r < 0) + r = omapdss_device_init_output(out, &sdi->bridge); + if (r < 0) { + sdi_bridge_cleanup(sdi); return r; + } omapdss_device_register(out); @@ -284,6 +332,8 @@ static void sdi_uninit_output(struct sdi_device *sdi) { omapdss_device_unregister(&sdi->output); omapdss_device_cleanup_output(&sdi->output); + + sdi_bridge_cleanup(sdi); } int sdi_init_port(struct dss_device *dss, struct platform_device *pdev, |