Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Thu, Dec 14, 2017 at 11:30:21AM +0800, Chen-Yu Tsai wrote: > >> > + /* Map output pins to channel 0 */ > >> > + regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, > >> > + SUN4I_TCON_GCTL_IOMAP_MASK, > >> > + SUN4I_TCON_GCTL_IOMAP_TCON0); > >> > + > >> > + /* Enable the output on the pins */ > >> > + regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe000); > >> > >> Is this still needed? You are no longer using the TCON LCD pins > >> with LVDS. > > > > We do. It's a separate function of the pins, but it's the same pins. > > OK. I assume you've tried it without setting it and it failed? > I just assume that these refer to the TCON LCD output, whereas > LVDS looks like a separate module and function, and shouldn't > need it. Argh, I forgot to test that. I'll test it for real this time and will update that part with a comment if that's needed. Sorry :/ Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Thu, Dec 14, 2017 at 11:30:21AM +0800, Chen-Yu Tsai wrote: > >> > + /* Map output pins to channel 0 */ > >> > + regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, > >> > + SUN4I_TCON_GCTL_IOMAP_MASK, > >> > + SUN4I_TCON_GCTL_IOMAP_TCON0); > >> > + > >> > + /* Enable the output on the pins */ > >> > + regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe000); > >> > >> Is this still needed? You are no longer using the TCON LCD pins > >> with LVDS. > > > > We do. It's a separate function of the pins, but it's the same pins. > > OK. I assume you've tried it without setting it and it failed? > I just assume that these refer to the TCON LCD output, whereas > LVDS looks like a separate module and function, and shouldn't > need it. Argh, I forgot to test that. I'll test it for real this time and will update that part with a comment if that's needed. Sorry :/ Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Thu, Dec 7, 2017 at 8:25 PM, Maxime Ripardwrote: > Hi, > > On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote: >> > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, >> > + const struct drm_encoder *encoder, >> > + bool enabled) >> > +{ >> > + if (enabled) { >> > + u8 val; >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, >> > + SUN4I_TCON0_LVDS_IF_EN, >> > + SUN4I_TCON0_LVDS_IF_EN); >> > + >> > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > +SUN4I_TCON0_LVDS_ANA0_C(2) | >> > +SUN4I_TCON0_LVDS_ANA0_V(3) | >> > +SUN4I_TCON0_LVDS_ANA0_PD(2) | >> > +SUN4I_TCON0_LVDS_ANA0_EN_LDO); >> > + udelay(2); >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_MB, >> > + SUN4I_TCON0_LVDS_ANA0_EN_MB); >> > + udelay(2); >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC); >> > + >> > + if (sun4i_tcon_get_pixel_depth(encoder) == 18) >> > + val = 7; >> > + else >> > + val = 0xf; >> > + >> > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf), >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val)); >> >> I suggest changing the prefix of the macros of the analog bits to >> SUN6I_TCON0_*. The register definitions and sequence do not apply >> to the A10/A20. Furthermore you should add a comment saying this >> doesn't apply to the A10/A20. In the future we might want to move >> this part into a separate function, referenced by a function pointer >> from the quirks structure. > > I'll change the bit field names and add a comment like you suggested. > >> > + } else { >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, >> > + SUN4I_TCON0_LVDS_IF_EN, 0); >> > + } >> > +} >> > + >> > void sun4i_tcon_set_status(struct sun4i_tcon *tcon, >> >const struct drm_encoder *encoder, >> >bool enabled) >> > { >> > + bool is_lvds = false; >> > int channel; >> > >> > switch (encoder->encoder_type) { >> > + case DRM_MODE_ENCODER_LVDS: >> > + is_lvds = true; >> > + /* Fallthrough */ >> > case DRM_MODE_ENCODER_NONE: >> > channel = 0; >> > break; >> > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, >> > return; >> > } >> > >> > + if (is_lvds && !enabled) >> > + sun4i_tcon_lvds_set_status(tcon, encoder, false); >> > + >> > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, >> >SUN4I_TCON_GCTL_TCON_ENABLE, >> >enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0); >> > >> > + if (is_lvds && enabled) >> > + sun4i_tcon_lvds_set_status(tcon, encoder, true); >> > + >> > sun4i_tcon_channel_set_status(tcon, channel, enabled); >> > } >> > >> > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct >> > sun4i_tcon *tcon, >> > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); >> > } >> > >> > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, >> > + const struct drm_encoder *encoder, >> > + const struct drm_display_mode *mode) >> > +{ >> > + unsigned int bp; >> > + u8 clk_delay; >> > + u32 reg, val = 0; >> > + >> > + tcon->dclk_min_div = 7; >> > + tcon->dclk_max_div = 7; >> > + sun4i_tcon0_mode_set_common(tcon, mode); >> > + >> > + /* Adjust clock delay */ >> > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, >> > + SUN4I_TCON0_CTL_CLK_DELAY_MASK, >> > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); >> > + >> > + /* >> > +* This is called a backporch in the register documentation, >> > +* but it really is the back porch + hsync >> > +*/ >> > + bp = mode->crtc_htotal - mode->crtc_hsync_start; >> > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", >> > +
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Thu, Dec 7, 2017 at 8:25 PM, Maxime Ripard wrote: > Hi, > > On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote: >> > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, >> > + const struct drm_encoder *encoder, >> > + bool enabled) >> > +{ >> > + if (enabled) { >> > + u8 val; >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, >> > + SUN4I_TCON0_LVDS_IF_EN, >> > + SUN4I_TCON0_LVDS_IF_EN); >> > + >> > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > +SUN4I_TCON0_LVDS_ANA0_C(2) | >> > +SUN4I_TCON0_LVDS_ANA0_V(3) | >> > +SUN4I_TCON0_LVDS_ANA0_PD(2) | >> > +SUN4I_TCON0_LVDS_ANA0_EN_LDO); >> > + udelay(2); >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_MB, >> > + SUN4I_TCON0_LVDS_ANA0_EN_MB); >> > + udelay(2); >> > + >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC); >> > + >> > + if (sun4i_tcon_get_pixel_depth(encoder) == 18) >> > + val = 7; >> > + else >> > + val = 0xf; >> > + >> > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf), >> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val)); >> >> I suggest changing the prefix of the macros of the analog bits to >> SUN6I_TCON0_*. The register definitions and sequence do not apply >> to the A10/A20. Furthermore you should add a comment saying this >> doesn't apply to the A10/A20. In the future we might want to move >> this part into a separate function, referenced by a function pointer >> from the quirks structure. > > I'll change the bit field names and add a comment like you suggested. > >> > + } else { >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, >> > + SUN4I_TCON0_LVDS_IF_EN, 0); >> > + } >> > +} >> > + >> > void sun4i_tcon_set_status(struct sun4i_tcon *tcon, >> >const struct drm_encoder *encoder, >> >bool enabled) >> > { >> > + bool is_lvds = false; >> > int channel; >> > >> > switch (encoder->encoder_type) { >> > + case DRM_MODE_ENCODER_LVDS: >> > + is_lvds = true; >> > + /* Fallthrough */ >> > case DRM_MODE_ENCODER_NONE: >> > channel = 0; >> > break; >> > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, >> > return; >> > } >> > >> > + if (is_lvds && !enabled) >> > + sun4i_tcon_lvds_set_status(tcon, encoder, false); >> > + >> > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, >> >SUN4I_TCON_GCTL_TCON_ENABLE, >> >enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0); >> > >> > + if (is_lvds && enabled) >> > + sun4i_tcon_lvds_set_status(tcon, encoder, true); >> > + >> > sun4i_tcon_channel_set_status(tcon, channel, enabled); >> > } >> > >> > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct >> > sun4i_tcon *tcon, >> > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); >> > } >> > >> > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, >> > + const struct drm_encoder *encoder, >> > + const struct drm_display_mode *mode) >> > +{ >> > + unsigned int bp; >> > + u8 clk_delay; >> > + u32 reg, val = 0; >> > + >> > + tcon->dclk_min_div = 7; >> > + tcon->dclk_max_div = 7; >> > + sun4i_tcon0_mode_set_common(tcon, mode); >> > + >> > + /* Adjust clock delay */ >> > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); >> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, >> > + SUN4I_TCON0_CTL_CLK_DELAY_MASK, >> > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); >> > + >> > + /* >> > +* This is called a backporch in the register documentation, >> > +* but it really is the back porch + hsync >> > +*/ >> > + bp = mode->crtc_htotal - mode->crtc_hsync_start; >> > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", >> > +mode->crtc_htotal, bp); >> >
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
Hi, On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote: > > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, > > + const struct drm_encoder *encoder, > > + bool enabled) > > +{ > > + if (enabled) { > > + u8 val; > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, > > + SUN4I_TCON0_LVDS_IF_EN, > > + SUN4I_TCON0_LVDS_IF_EN); > > + > > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > +SUN4I_TCON0_LVDS_ANA0_C(2) | > > +SUN4I_TCON0_LVDS_ANA0_V(3) | > > +SUN4I_TCON0_LVDS_ANA0_PD(2) | > > +SUN4I_TCON0_LVDS_ANA0_EN_LDO); > > + udelay(2); > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_MB, > > + SUN4I_TCON0_LVDS_ANA0_EN_MB); > > + udelay(2); > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC); > > + > > + if (sun4i_tcon_get_pixel_depth(encoder) == 18) > > + val = 7; > > + else > > + val = 0xf; > > + > > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf), > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val)); > > I suggest changing the prefix of the macros of the analog bits to > SUN6I_TCON0_*. The register definitions and sequence do not apply > to the A10/A20. Furthermore you should add a comment saying this > doesn't apply to the A10/A20. In the future we might want to move > this part into a separate function, referenced by a function pointer > from the quirks structure. I'll change the bit field names and add a comment like you suggested. > > + } else { > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, > > + SUN4I_TCON0_LVDS_IF_EN, 0); > > + } > > +} > > + > > void sun4i_tcon_set_status(struct sun4i_tcon *tcon, > >const struct drm_encoder *encoder, > >bool enabled) > > { > > + bool is_lvds = false; > > int channel; > > > > switch (encoder->encoder_type) { > > + case DRM_MODE_ENCODER_LVDS: > > + is_lvds = true; > > + /* Fallthrough */ > > case DRM_MODE_ENCODER_NONE: > > channel = 0; > > break; > > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, > > return; > > } > > > > + if (is_lvds && !enabled) > > + sun4i_tcon_lvds_set_status(tcon, encoder, false); > > + > > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, > >SUN4I_TCON_GCTL_TCON_ENABLE, > >enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0); > > > > + if (is_lvds && enabled) > > + sun4i_tcon_lvds_set_status(tcon, encoder, true); > > + > > sun4i_tcon_channel_set_status(tcon, channel, enabled); > > } > > > > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct > > sun4i_tcon *tcon, > > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); > > } > > > > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, > > + const struct drm_encoder *encoder, > > + const struct drm_display_mode *mode) > > +{ > > + unsigned int bp; > > + u8 clk_delay; > > + u32 reg, val = 0; > > + > > + tcon->dclk_min_div = 7; > > + tcon->dclk_max_div = 7; > > + sun4i_tcon0_mode_set_common(tcon, mode); > > + > > + /* Adjust clock delay */ > > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, > > + SUN4I_TCON0_CTL_CLK_DELAY_MASK, > > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); > > + > > + /* > > +* This is called a backporch in the register documentation, > > +* but it really is the back porch + hsync > > +*/ > > + bp = mode->crtc_htotal - mode->crtc_hsync_start; > > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", > > +mode->crtc_htotal, bp); > > + > > + /* Set horizontal display timings */ > > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG, > > +
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
Hi, On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote: > > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, > > + const struct drm_encoder *encoder, > > + bool enabled) > > +{ > > + if (enabled) { > > + u8 val; > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, > > + SUN4I_TCON0_LVDS_IF_EN, > > + SUN4I_TCON0_LVDS_IF_EN); > > + > > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > +SUN4I_TCON0_LVDS_ANA0_C(2) | > > +SUN4I_TCON0_LVDS_ANA0_V(3) | > > +SUN4I_TCON0_LVDS_ANA0_PD(2) | > > +SUN4I_TCON0_LVDS_ANA0_EN_LDO); > > + udelay(2); > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_MB, > > + SUN4I_TCON0_LVDS_ANA0_EN_MB); > > + udelay(2); > > + > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC); > > + > > + if (sun4i_tcon_get_pixel_depth(encoder) == 18) > > + val = 7; > > + else > > + val = 0xf; > > + > > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf), > > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val)); > > I suggest changing the prefix of the macros of the analog bits to > SUN6I_TCON0_*. The register definitions and sequence do not apply > to the A10/A20. Furthermore you should add a comment saying this > doesn't apply to the A10/A20. In the future we might want to move > this part into a separate function, referenced by a function pointer > from the quirks structure. I'll change the bit field names and add a comment like you suggested. > > + } else { > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, > > + SUN4I_TCON0_LVDS_IF_EN, 0); > > + } > > +} > > + > > void sun4i_tcon_set_status(struct sun4i_tcon *tcon, > >const struct drm_encoder *encoder, > >bool enabled) > > { > > + bool is_lvds = false; > > int channel; > > > > switch (encoder->encoder_type) { > > + case DRM_MODE_ENCODER_LVDS: > > + is_lvds = true; > > + /* Fallthrough */ > > case DRM_MODE_ENCODER_NONE: > > channel = 0; > > break; > > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, > > return; > > } > > > > + if (is_lvds && !enabled) > > + sun4i_tcon_lvds_set_status(tcon, encoder, false); > > + > > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, > >SUN4I_TCON_GCTL_TCON_ENABLE, > >enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0); > > > > + if (is_lvds && enabled) > > + sun4i_tcon_lvds_set_status(tcon, encoder, true); > > + > > sun4i_tcon_channel_set_status(tcon, channel, enabled); > > } > > > > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct > > sun4i_tcon *tcon, > > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); > > } > > > > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, > > + const struct drm_encoder *encoder, > > + const struct drm_display_mode *mode) > > +{ > > + unsigned int bp; > > + u8 clk_delay; > > + u32 reg, val = 0; > > + > > + tcon->dclk_min_div = 7; > > + tcon->dclk_max_div = 7; > > + sun4i_tcon0_mode_set_common(tcon, mode); > > + > > + /* Adjust clock delay */ > > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); > > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, > > + SUN4I_TCON0_CTL_CLK_DELAY_MASK, > > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); > > + > > + /* > > +* This is called a backporch in the register documentation, > > +* but it really is the back porch + hsync > > +*/ > > + bp = mode->crtc_htotal - mode->crtc_hsync_start; > > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", > > +mode->crtc_htotal, bp); > > + > > + /* Set horizontal display timings */ > > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG, > > +
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
Hi, On Thu, Dec 07, 2017 at 11:14:27AM +0100, Philippe Ombredanne wrote: > On Tue, Dec 5, 2017 at 4:10 PM, Maxime Ripard >wrote: > > The TCON supports the LVDS interface to output to a panel or a bridge. > > Let's add support for it. > > > > Signed-off-by: Maxime Ripard > [] > > --- /dev/null > > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > > @@ -0,0 +1,183 @@ > > +/* > > + * Copyright (C) 2015 NextThing Co > > + * Copyright (C) 2015-2017 Free Electrons > > + * > > + * Maxime Ripard > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License as > > + * published by the Free Software Foundation; either version 2 of > > + * the License, or (at your option) any later version. > > + */ > > Would you consider using the new SPDX ids instead of this fine legalese? > e.g. this as the top line: > > // SPDX-License-Identifier: GPL-2.0+ I did, and then forgot about it. This will be in my next iteration, thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
Hi, On Thu, Dec 07, 2017 at 11:14:27AM +0100, Philippe Ombredanne wrote: > On Tue, Dec 5, 2017 at 4:10 PM, Maxime Ripard > wrote: > > The TCON supports the LVDS interface to output to a panel or a bridge. > > Let's add support for it. > > > > Signed-off-by: Maxime Ripard > [] > > --- /dev/null > > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > > @@ -0,0 +1,183 @@ > > +/* > > + * Copyright (C) 2015 NextThing Co > > + * Copyright (C) 2015-2017 Free Electrons > > + * > > + * Maxime Ripard > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License as > > + * published by the Free Software Foundation; either version 2 of > > + * the License, or (at your option) any later version. > > + */ > > Would you consider using the new SPDX ids instead of this fine legalese? > e.g. this as the top line: > > // SPDX-License-Identifier: GPL-2.0+ I did, and then forgot about it. This will be in my next iteration, thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Tue, Dec 5, 2017 at 4:10 PM, Maxime Ripardwrote: > The TCON supports the LVDS interface to output to a panel or a bridge. > Let's add support for it. > > Signed-off-by: Maxime Ripard [] > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > @@ -0,0 +1,183 @@ > +/* > + * Copyright (C) 2015 NextThing Co > + * Copyright (C) 2015-2017 Free Electrons > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ Maxime, Would you consider using the new SPDX ids instead of this fine legalese? e.g. this as the top line: // SPDX-License-Identifier: GPL-2.0+ -- Cordially Philippe Ombredanne
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Tue, Dec 5, 2017 at 4:10 PM, Maxime Ripard wrote: > The TCON supports the LVDS interface to output to a panel or a bridge. > Let's add support for it. > > Signed-off-by: Maxime Ripard [] > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > @@ -0,0 +1,183 @@ > +/* > + * Copyright (C) 2015 NextThing Co > + * Copyright (C) 2015-2017 Free Electrons > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ Maxime, Would you consider using the new SPDX ids instead of this fine legalese? e.g. this as the top line: // SPDX-License-Identifier: GPL-2.0+ -- Cordially Philippe Ombredanne
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Tue, Dec 5, 2017 at 11:10 PM, Maxime Ripardwrote: > The TCON supports the LVDS interface to output to a panel or a bridge. > Let's add support for it. > > Signed-off-by: Maxime Ripard > --- > drivers/gpu/drm/sun4i/Makefile | 1 +- > drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 +++- > drivers/gpu/drm/sun4i/sun4i_lvds.h | 18 ++- > drivers/gpu/drm/sun4i/sun4i_tcon.c | 238 +- > drivers/gpu/drm/sun4i/sun4i_tcon.h | 29 - > 5 files changed, 467 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h > > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile > index 82a6ac57fbe3..2b37a6abbb1d 100644 > --- a/drivers/gpu/drm/sun4i/Makefile > +++ b/drivers/gpu/drm/sun4i/Makefile > @@ -15,6 +15,7 @@ sun8i-mixer-y += sun8i_mixer.o > sun8i_ui_layer.o \ > > sun4i-tcon-y += sun4i_crtc.o > sun4i-tcon-y += sun4i_dotclock.o > +sun4i-tcon-y += sun4i_lvds.o > sun4i-tcon-y += sun4i_tcon.o > sun4i-tcon-y += sun4i_rgb.o > > diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c > b/drivers/gpu/drm/sun4i/sun4i_lvds.c > new file mode 100644 > index ..635a3f505ecb > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > @@ -0,0 +1,183 @@ > +/* > + * Copyright (C) 2015 NextThing Co > + * Copyright (C) 2015-2017 Free Electrons > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include "sun4i_crtc.h" > +#include "sun4i_tcon.h" > +#include "sun4i_lvds.h" > + > +struct sun4i_lvds { > + struct drm_connectorconnector; > + struct drm_encoder encoder; > + > + struct sun4i_tcon *tcon; > +}; > + > +static inline struct sun4i_lvds * > +drm_connector_to_sun4i_lvds(struct drm_connector *connector) > +{ > + return container_of(connector, struct sun4i_lvds, > + connector); > +} > + > +static inline struct sun4i_lvds * > +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder) > +{ > + return container_of(encoder, struct sun4i_lvds, > + encoder); > +} > + > +static int sun4i_lvds_get_modes(struct drm_connector *connector) > +{ > + struct sun4i_lvds *lvds = > + drm_connector_to_sun4i_lvds(connector); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + return drm_panel_get_modes(tcon->panel); > +} > + > +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { > + .get_modes = sun4i_lvds_get_modes, > +}; > + > +static void > +sun4i_lvds_connector_destroy(struct drm_connector *connector) > +{ > + struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + drm_panel_detach(tcon->panel); > + drm_connector_cleanup(connector); > +} > + > +static const struct drm_connector_funcs sun4i_lvds_con_funcs = { > + .fill_modes = drm_helper_probe_single_connector_modes, > + .destroy= sun4i_lvds_connector_destroy, > + .reset = drm_atomic_helper_connector_reset, > + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > +}; > + > +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder) > +{ > + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + DRM_DEBUG_DRIVER("Enabling LVDS output\n"); > + > + if (!IS_ERR(tcon->panel)) { > + drm_panel_prepare(tcon->panel); > + drm_panel_enable(tcon->panel); > + } > +} > + > +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder) > +{ > + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + DRM_DEBUG_DRIVER("Disabling LVDS output\n"); > + > + if (!IS_ERR(tcon->panel)) { > + drm_panel_disable(tcon->panel); > + drm_panel_unprepare(tcon->panel); > + } > +} > + > +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = { > + .disable= sun4i_lvds_encoder_disable, > + .enable = sun4i_lvds_encoder_enable, > +}; > + > +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = { > + .destroy=
Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
On Tue, Dec 5, 2017 at 11:10 PM, Maxime Ripard wrote: > The TCON supports the LVDS interface to output to a panel or a bridge. > Let's add support for it. > > Signed-off-by: Maxime Ripard > --- > drivers/gpu/drm/sun4i/Makefile | 1 +- > drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 +++- > drivers/gpu/drm/sun4i/sun4i_lvds.h | 18 ++- > drivers/gpu/drm/sun4i/sun4i_tcon.c | 238 +- > drivers/gpu/drm/sun4i/sun4i_tcon.h | 29 - > 5 files changed, 467 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h > > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile > index 82a6ac57fbe3..2b37a6abbb1d 100644 > --- a/drivers/gpu/drm/sun4i/Makefile > +++ b/drivers/gpu/drm/sun4i/Makefile > @@ -15,6 +15,7 @@ sun8i-mixer-y += sun8i_mixer.o > sun8i_ui_layer.o \ > > sun4i-tcon-y += sun4i_crtc.o > sun4i-tcon-y += sun4i_dotclock.o > +sun4i-tcon-y += sun4i_lvds.o > sun4i-tcon-y += sun4i_tcon.o > sun4i-tcon-y += sun4i_rgb.o > > diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c > b/drivers/gpu/drm/sun4i/sun4i_lvds.c > new file mode 100644 > index ..635a3f505ecb > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c > @@ -0,0 +1,183 @@ > +/* > + * Copyright (C) 2015 NextThing Co > + * Copyright (C) 2015-2017 Free Electrons > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include "sun4i_crtc.h" > +#include "sun4i_tcon.h" > +#include "sun4i_lvds.h" > + > +struct sun4i_lvds { > + struct drm_connectorconnector; > + struct drm_encoder encoder; > + > + struct sun4i_tcon *tcon; > +}; > + > +static inline struct sun4i_lvds * > +drm_connector_to_sun4i_lvds(struct drm_connector *connector) > +{ > + return container_of(connector, struct sun4i_lvds, > + connector); > +} > + > +static inline struct sun4i_lvds * > +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder) > +{ > + return container_of(encoder, struct sun4i_lvds, > + encoder); > +} > + > +static int sun4i_lvds_get_modes(struct drm_connector *connector) > +{ > + struct sun4i_lvds *lvds = > + drm_connector_to_sun4i_lvds(connector); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + return drm_panel_get_modes(tcon->panel); > +} > + > +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { > + .get_modes = sun4i_lvds_get_modes, > +}; > + > +static void > +sun4i_lvds_connector_destroy(struct drm_connector *connector) > +{ > + struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + drm_panel_detach(tcon->panel); > + drm_connector_cleanup(connector); > +} > + > +static const struct drm_connector_funcs sun4i_lvds_con_funcs = { > + .fill_modes = drm_helper_probe_single_connector_modes, > + .destroy= sun4i_lvds_connector_destroy, > + .reset = drm_atomic_helper_connector_reset, > + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > +}; > + > +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder) > +{ > + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + DRM_DEBUG_DRIVER("Enabling LVDS output\n"); > + > + if (!IS_ERR(tcon->panel)) { > + drm_panel_prepare(tcon->panel); > + drm_panel_enable(tcon->panel); > + } > +} > + > +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder) > +{ > + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); > + struct sun4i_tcon *tcon = lvds->tcon; > + > + DRM_DEBUG_DRIVER("Disabling LVDS output\n"); > + > + if (!IS_ERR(tcon->panel)) { > + drm_panel_disable(tcon->panel); > + drm_panel_unprepare(tcon->panel); > + } > +} > + > +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = { > + .disable= sun4i_lvds_encoder_disable, > + .enable = sun4i_lvds_encoder_enable, > +}; > + > +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = { > + .destroy= drm_encoder_cleanup, > +}; > + > +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon) > +{ >
[PATCH v3 08/15] drm/sun4i: Add LVDS support
The TCON supports the LVDS interface to output to a panel or a bridge. Let's add support for it. Signed-off-by: Maxime Ripard--- drivers/gpu/drm/sun4i/Makefile | 1 +- drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 +++- drivers/gpu/drm/sun4i/sun4i_lvds.h | 18 ++- drivers/gpu/drm/sun4i/sun4i_tcon.c | 238 +- drivers/gpu/drm/sun4i/sun4i_tcon.h | 29 - 5 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 82a6ac57fbe3..2b37a6abbb1d 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -15,6 +15,7 @@ sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ sun4i-tcon-y += sun4i_crtc.o sun4i-tcon-y += sun4i_dotclock.o +sun4i-tcon-y += sun4i_lvds.o sun4i-tcon-y += sun4i_tcon.o sun4i-tcon-y += sun4i_rgb.o diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c new file mode 100644 index ..635a3f505ecb --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2015 NextThing Co + * Copyright (C) 2015-2017 Free Electrons + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include + +#include +#include +#include +#include +#include + +#include "sun4i_crtc.h" +#include "sun4i_tcon.h" +#include "sun4i_lvds.h" + +struct sun4i_lvds { + struct drm_connectorconnector; + struct drm_encoder encoder; + + struct sun4i_tcon *tcon; +}; + +static inline struct sun4i_lvds * +drm_connector_to_sun4i_lvds(struct drm_connector *connector) +{ + return container_of(connector, struct sun4i_lvds, + connector); +} + +static inline struct sun4i_lvds * +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder) +{ + return container_of(encoder, struct sun4i_lvds, + encoder); +} + +static int sun4i_lvds_get_modes(struct drm_connector *connector) +{ + struct sun4i_lvds *lvds = + drm_connector_to_sun4i_lvds(connector); + struct sun4i_tcon *tcon = lvds->tcon; + + return drm_panel_get_modes(tcon->panel); +} + +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { + .get_modes = sun4i_lvds_get_modes, +}; + +static void +sun4i_lvds_connector_destroy(struct drm_connector *connector) +{ + struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector); + struct sun4i_tcon *tcon = lvds->tcon; + + drm_panel_detach(tcon->panel); + drm_connector_cleanup(connector); +} + +static const struct drm_connector_funcs sun4i_lvds_con_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy= sun4i_lvds_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder) +{ + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); + struct sun4i_tcon *tcon = lvds->tcon; + + DRM_DEBUG_DRIVER("Enabling LVDS output\n"); + + if (!IS_ERR(tcon->panel)) { + drm_panel_prepare(tcon->panel); + drm_panel_enable(tcon->panel); + } +} + +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder) +{ + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); + struct sun4i_tcon *tcon = lvds->tcon; + + DRM_DEBUG_DRIVER("Disabling LVDS output\n"); + + if (!IS_ERR(tcon->panel)) { + drm_panel_disable(tcon->panel); + drm_panel_unprepare(tcon->panel); + } +} + +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = { + .disable= sun4i_lvds_encoder_disable, + .enable = sun4i_lvds_encoder_enable, +}; + +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = { + .destroy= drm_encoder_cleanup, +}; + +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon) +{ + struct drm_encoder *encoder; + struct drm_bridge *bridge; + struct sun4i_lvds *lvds; + int ret; + + lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL); + if (!lvds) + return -ENOMEM; + lvds->tcon = tcon; +
[PATCH v3 08/15] drm/sun4i: Add LVDS support
The TCON supports the LVDS interface to output to a panel or a bridge. Let's add support for it. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/Makefile | 1 +- drivers/gpu/drm/sun4i/sun4i_lvds.c | 183 +++- drivers/gpu/drm/sun4i/sun4i_lvds.h | 18 ++- drivers/gpu/drm/sun4i/sun4i_tcon.c | 238 +- drivers/gpu/drm/sun4i/sun4i_tcon.h | 29 - 5 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 82a6ac57fbe3..2b37a6abbb1d 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -15,6 +15,7 @@ sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ sun4i-tcon-y += sun4i_crtc.o sun4i-tcon-y += sun4i_dotclock.o +sun4i-tcon-y += sun4i_lvds.o sun4i-tcon-y += sun4i_tcon.o sun4i-tcon-y += sun4i_rgb.o diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c new file mode 100644 index ..635a3f505ecb --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2015 NextThing Co + * Copyright (C) 2015-2017 Free Electrons + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include + +#include +#include +#include +#include +#include + +#include "sun4i_crtc.h" +#include "sun4i_tcon.h" +#include "sun4i_lvds.h" + +struct sun4i_lvds { + struct drm_connectorconnector; + struct drm_encoder encoder; + + struct sun4i_tcon *tcon; +}; + +static inline struct sun4i_lvds * +drm_connector_to_sun4i_lvds(struct drm_connector *connector) +{ + return container_of(connector, struct sun4i_lvds, + connector); +} + +static inline struct sun4i_lvds * +drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder) +{ + return container_of(encoder, struct sun4i_lvds, + encoder); +} + +static int sun4i_lvds_get_modes(struct drm_connector *connector) +{ + struct sun4i_lvds *lvds = + drm_connector_to_sun4i_lvds(connector); + struct sun4i_tcon *tcon = lvds->tcon; + + return drm_panel_get_modes(tcon->panel); +} + +static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { + .get_modes = sun4i_lvds_get_modes, +}; + +static void +sun4i_lvds_connector_destroy(struct drm_connector *connector) +{ + struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector); + struct sun4i_tcon *tcon = lvds->tcon; + + drm_panel_detach(tcon->panel); + drm_connector_cleanup(connector); +} + +static const struct drm_connector_funcs sun4i_lvds_con_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy= sun4i_lvds_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder) +{ + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); + struct sun4i_tcon *tcon = lvds->tcon; + + DRM_DEBUG_DRIVER("Enabling LVDS output\n"); + + if (!IS_ERR(tcon->panel)) { + drm_panel_prepare(tcon->panel); + drm_panel_enable(tcon->panel); + } +} + +static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder) +{ + struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder); + struct sun4i_tcon *tcon = lvds->tcon; + + DRM_DEBUG_DRIVER("Disabling LVDS output\n"); + + if (!IS_ERR(tcon->panel)) { + drm_panel_disable(tcon->panel); + drm_panel_unprepare(tcon->panel); + } +} + +static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = { + .disable= sun4i_lvds_encoder_disable, + .enable = sun4i_lvds_encoder_enable, +}; + +static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = { + .destroy= drm_encoder_cleanup, +}; + +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon) +{ + struct drm_encoder *encoder; + struct drm_bridge *bridge; + struct sun4i_lvds *lvds; + int ret; + + lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL); + if (!lvds) + return -ENOMEM; + lvds->tcon = tcon; + encoder = >encoder; + + ret =