[PATCH 3/3] drm/bridge: sii9234: use extcon cable detection logic to detect MHL
Henrik Grimler
henrik at grimler.se
Fri Aug 8 07:39:34 UTC 2025
Hi Marek,
On Fri, Aug 01, 2025 at 10:09:08AM +0200, Marek Szyprowski wrote:
> On 21.07.2025 11:43, Henrik Grimler wrote:
> > To use MHL we currently need the MHL chip to be permanently on, which
> > consumes unnecessary power. Let's use extcon attached to MUIC to enable
> > the MHL chip only if it detects an MHL cable.
> >
> > Signed-off-by: Henrik Grimler <henrik at grimler.se>
> > ---
>
> Thanks!
>
> Acked-by: Marek Szyprowski <m.szyprowski at samsung.com>
> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Thanks for testing! On trats2 I assume? After some more testing I
noticed that mhl hotplugging only works reliably if device screen is
on when cable is plugged in, otherwise I get errors like:
[ 281.203520] exynos-hdmi 12d00000.hdmi: [drm:hdmiphy_enable.part.0] *ERROR* PLL could not reach steady state
[ 281.313816] exynos-mixer 12c10000.mixer: timeout waiting for VSYNC
[ 281.420637] ------------[ cut here ]------------
[ 281.423861] WARNING: CPU: 3 PID: 1189 at drivers/gpu/drm/drm_atomic_helper.c:1720 drm_atomic_helper_wait_for_vblanks.part.0+0x264/0x26c
[ 281.436172] [CRTC:71:crtc-1] vblank wait timed out
[ 281.440870] Modules linked in: cpufreq_conservative rfcomm aes_arm aes_generic nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 cmac nft_reject algif_hash algif_skcipher nft_ct nf_conntrack af_alg nf_defrag_ipv6 nf_defrag_ipv4 bnep nf_tables ntc_thermistor hwmon brcmfmac_wcc s5k6a3 st_accel_spi spi_s3c64xx st_gyro_spi hci_uart st_sensors_spi btbcm btintel pwm_samsung bluetooth st_gyro_i2c st_accel_i2c st_gyro st_sensors_i2c st_accel st_sensors brcmfmac ecdh_generic ecc s5c73m3 libaes lima cfg80211 drm_shmem_helper gpu_sched exynos_adc brcmutil rfkill panel_samsung_s6e8aa0 s5p_sss exynos_rng s5p_g2d tm2_touchkey leds_an30259a cm36651 leds_aat1290 led_class_flash led_class ak8975 industrialio_triggered_buffer kfifo_buf gpio_keys uhid hid uinput ledtrig_pattern zram zsmalloc fuse loop nfnetlink ipv6 evdev [last unloaded: cpufreq_conservative]
[ 281.514974] CPU: 3 UID: 10000 PID: 1189 Comm: phoc Tainted: G W 6.16.0-postmarketos-exynos4 #38 PREEMPT
[ 281.515007] Tainted: [W]=WARN
[ 281.515013] Hardware name: Samsung Exynos (Flattened Device Tree)
[ 281.515027] Call trace:
[ 281.515062] unwind_backtrace from show_stack+0x18/0x1c
[ 281.515155] show_stack from dump_stack_lvl+0x50/0x64
[ 281.515219] dump_stack_lvl from __warn+0x88/0x15c
[ 281.515271] __warn from warn_slowpath_fmt+0x118/0x1ac
[ 281.515285] warn_slowpath_fmt from drm_atomic_helper_wait_for_vblanks.part.0+0x264/0x26c
[ 281.515340] drm_atomic_helper_wait_for_vblanks.part.0 from drm_atomic_helper_commit_tail_rpm+0x84/0x94
[ 281.515363] drm_atomic_helper_commit_tail_rpm from commit_tail+0xa8/0x1a0
[ 281.515385] commit_tail from drm_atomic_helper_commit+0x164/0x19c
[ 281.515402] drm_atomic_helper_commit from drm_atomic_commit+0xd0/0x104
[ 281.515489] drm_atomic_commit from drm_mode_atomic_ioctl+0x9f8/0xd14
[ 281.515512] drm_mode_atomic_ioctl from drm_ioctl+0x20c/0x4cc
[ 281.515562] drm_ioctl from sys_ioctl+0x5a8/0xc10
[ 281.515634] sys_ioctl from ret_fast_syscall+0x0/0x54
[ 281.515651] Exception stack(0xc5d05fa8 to 0xc5d05ff0)
[ 281.515665] 5fa0: beb4be88 beb4be88 0000000d c03864bc beb4be88 0000000d
[ 281.515675] 5fc0: beb4be88 beb4be88 c03864bc 00000036 acbe4450 ad8edc70 acbe4490 acd46cf0
[ 281.515682] 5fe0: beb4be58 beb4bd38 b6e5651f b6ebb040
[ 281.515693] ---[ end trace 0000000000000000 ]---
or device just hangs. I suppose this might not be an issue in the
sii9234 driver though, so will collect your tags (unless I do further
changes)!
> You should also add "select EXTCON" (like in case of Sii8620) to Kconfig
> to avoid potential build break if extcon support is built as a module.
Kernel robot also reported this issue, so I have added the select in
v2:
https://lore.kernel.org/linux-samsung-soc/20250724-exynos4-sii9234-driver-v2-0-faee244f1d40@grimler.se/
Best regards,
Henrik Grimler
>
> > drivers/gpu/drm/bridge/sii9234.c | 89 ++++++++++++++++++++++++++++++++++++++--
> > 1 file changed, 86 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
> > index 0e0bb1bf71fdcef788715cfd6fa158a6992def33..4d84ba01ea76816bebdbc29d48a041c9c6cd508e 100644
> > --- a/drivers/gpu/drm/bridge/sii9234.c
> > +++ b/drivers/gpu/drm/bridge/sii9234.c
> > @@ -19,6 +19,7 @@
> >
> > #include <linux/delay.h>
> > #include <linux/err.h>
> > +#include <linux/extcon.h>
> > #include <linux/gpio/consumer.h>
> > #include <linux/i2c.h>
> > #include <linux/interrupt.h>
> > @@ -26,6 +27,7 @@
> > #include <linux/kernel.h>
> > #include <linux/module.h>
> > #include <linux/mutex.h>
> > +#include <linux/of_graph.h>
> > #include <linux/regulator/consumer.h>
> > #include <linux/slab.h>
> >
> > @@ -170,8 +172,12 @@ struct sii9234 {
> > struct drm_bridge bridge;
> > struct device *dev;
> > struct gpio_desc *gpio_reset;
> > - int i2c_error;
> > struct regulator_bulk_data supplies[4];
> > + struct extcon_dev *extcon;
> > + struct notifier_block extcon_nb;
> > + struct work_struct extcon_wq;
> > + int cable_state;
> > + int i2c_error;
> >
> > struct mutex lock; /* Protects fields below and device registers */
> > enum sii9234_state state;
> > @@ -864,6 +870,70 @@ static int sii9234_init_resources(struct sii9234 *ctx,
> > return 0;
> > }
> >
> > +static void sii9234_extcon_work(struct work_struct *work)
> > +{
> > + struct sii9234 *ctx =
> > + container_of(work, struct sii9234, extcon_wq);
> > + int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL);
> > +
> > + if (state == ctx->cable_state)
> > + return;
> > +
> > + ctx->cable_state = state;
> > +
> > + if (state > 0)
> > + sii9234_cable_in(ctx);
> > + else
> > + sii9234_cable_out(ctx);
> > +}
> > +
> > +static int sii9234_extcon_notifier(struct notifier_block *self,
> > + unsigned long event, void *ptr)
> > +{
> > + struct sii9234 *ctx =
> > + container_of(self, struct sii9234, extcon_nb);
> > +
> > + schedule_work(&ctx->extcon_wq);
> > +
> > + return NOTIFY_DONE;
> > +}
> > +
> > +static int sii9234_extcon_init(struct sii9234 *ctx)
> > +{
> > + struct extcon_dev *edev;
> > + struct device_node *musb, *muic;
> > + int ret;
> > +
> > + /* Get micro-USB connector node */
> > + musb = of_graph_get_remote_node(ctx->dev->of_node, 1, -1);
> > + /* Then get micro-USB Interface Controller node */
> > + muic = of_get_next_parent(musb);
> > +
> > + if (!muic) {
> > + dev_info(ctx->dev,
> > + "no extcon found, switching to 'always on' mode\n");
> > + return 0;
> > + }
> > +
> > + edev = extcon_find_edev_by_node(muic);
> > + of_node_put(muic);
> > + if (IS_ERR(edev)) {
> > + dev_err_probe(ctx->dev, PTR_ERR(edev),
> > + "invalid or missing extcon\n");
> > + }
> > +
> > + ctx->extcon = edev;
> > + ctx->extcon_nb.notifier_call = sii9234_extcon_notifier;
> > + INIT_WORK(&ctx->extcon_wq, sii9234_extcon_work);
> > + ret = extcon_register_notifier(edev, EXTCON_DISP_MHL, &ctx->extcon_nb);
> > + if (ret) {
> > + dev_err(ctx->dev, "failed to register notifier for MHL\n");
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
> > const struct drm_display_info *info,
> > const struct drm_display_mode *mode)
> > @@ -916,12 +986,17 @@ static int sii9234_probe(struct i2c_client *client)
> > if (ret < 0)
> > return ret;
> >
> > + ret = sii9234_extcon_init(ctx);
> > + if (ret < 0)
> > + return ret;
> > +
> > i2c_set_clientdata(client, ctx);
> >
> > ctx->bridge.of_node = dev->of_node;
> > drm_bridge_add(&ctx->bridge);
> >
> > - sii9234_cable_in(ctx);
> > + if (!ctx->extcon)
> > + sii9234_cable_in(ctx);
> >
> > return 0;
> > }
> > @@ -930,7 +1005,15 @@ static void sii9234_remove(struct i2c_client *client)
> > {
> > struct sii9234 *ctx = i2c_get_clientdata(client);
> >
> > - sii9234_cable_out(ctx);
> > + if (ctx->extcon) {
> > + extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL,
> > + &ctx->extcon_nb);
> > + flush_work(&ctx->extcon_wq);
> > + if (ctx->cable_state > 0)
> > + sii9234_cable_out(ctx);
> > + } else {
> > + sii9234_cable_out(ctx);
> > + }
> > drm_bridge_remove(&ctx->bridge);
> > }
> >
> >
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>
More information about the dri-devel
mailing list