Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev into drm-next
rcar misc changes. * 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev: drm/rcar-du: Add support for the r8a7791 DU drm/rcar-du: Add LVDS_LANES quirk drm/rcar-du: Split features and quirks drm/rcar-du: Update plane pitch in .mode_set_base() operation drm/rcar-du: Don't cast crtc to rcrtc twice in the same function drm/rcar-du: fix return value check in rcar_du_lvdsenc_get_resources()
This commit is contained in:
commit
e6c3dcdea6
6 changed files with 58 additions and 23 deletions
|
@ -371,7 +371,6 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
rcrtc->plane->format = format;
|
rcrtc->plane->format = format;
|
||||||
rcrtc->plane->pitch = crtc->fb->pitches[0];
|
|
||||||
|
|
||||||
rcrtc->plane->src_x = x;
|
rcrtc->plane->src_x = x;
|
||||||
rcrtc->plane->src_y = y;
|
rcrtc->plane->src_y = y;
|
||||||
|
@ -413,7 +412,7 @@ static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||||
rcrtc->plane->src_x = x;
|
rcrtc->plane->src_x = x;
|
||||||
rcrtc->plane->src_y = y;
|
rcrtc->plane->src_y = y;
|
||||||
|
|
||||||
rcar_du_crtc_update_base(to_rcar_crtc(crtc));
|
rcar_du_crtc_update_base(rcrtc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,8 +251,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
|
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
|
||||||
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B
|
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
|
||||||
| RCAR_DU_FEATURE_DEFR8,
|
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
|
||||||
.num_crtcs = 3,
|
.num_crtcs = 3,
|
||||||
.routes = {
|
.routes = {
|
||||||
/* R8A7790 has one RGB output, two LVDS outputs and one
|
/* R8A7790 has one RGB output, two LVDS outputs and one
|
||||||
|
@ -274,9 +274,29 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
|
||||||
.num_lvds = 2,
|
.num_lvds = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
|
||||||
|
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
|
||||||
|
.num_crtcs = 2,
|
||||||
|
.routes = {
|
||||||
|
/* R8A7791 has one RGB output, one LVDS output and one
|
||||||
|
* (currently unsupported) TCON output.
|
||||||
|
*/
|
||||||
|
[RCAR_DU_OUTPUT_DPAD0] = {
|
||||||
|
.possible_crtcs = BIT(1),
|
||||||
|
.encoder_type = DRM_MODE_ENCODER_NONE,
|
||||||
|
},
|
||||||
|
[RCAR_DU_OUTPUT_LVDS0] = {
|
||||||
|
.possible_crtcs = BIT(0),
|
||||||
|
.encoder_type = DRM_MODE_ENCODER_LVDS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.num_lvds = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct platform_device_id rcar_du_id_table[] = {
|
static const struct platform_device_id rcar_du_id_table[] = {
|
||||||
{ "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
|
{ "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
|
||||||
{ "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
|
{ "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
|
||||||
|
{ "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,10 @@ struct rcar_du_device;
|
||||||
struct rcar_du_lvdsenc;
|
struct rcar_du_lvdsenc;
|
||||||
|
|
||||||
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
|
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
|
||||||
#define RCAR_DU_FEATURE_ALIGN_128B (1 << 1) /* Align pitches to 128 bytes */
|
#define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */
|
||||||
#define RCAR_DU_FEATURE_DEFR8 (1 << 2) /* Has DEFR8 register */
|
|
||||||
|
#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
|
||||||
|
#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct rcar_du_output_routing - Output routing specification
|
* struct rcar_du_output_routing - Output routing specification
|
||||||
|
@ -48,12 +50,14 @@ struct rcar_du_output_routing {
|
||||||
/*
|
/*
|
||||||
* struct rcar_du_device_info - DU model-specific information
|
* struct rcar_du_device_info - DU model-specific information
|
||||||
* @features: device features (RCAR_DU_FEATURE_*)
|
* @features: device features (RCAR_DU_FEATURE_*)
|
||||||
|
* @quirks: device quirks (RCAR_DU_QUIRK_*)
|
||||||
* @num_crtcs: total number of CRTCs
|
* @num_crtcs: total number of CRTCs
|
||||||
* @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
|
* @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
|
||||||
* @num_lvds: number of internal LVDS encoders
|
* @num_lvds: number of internal LVDS encoders
|
||||||
*/
|
*/
|
||||||
struct rcar_du_device_info {
|
struct rcar_du_device_info {
|
||||||
unsigned int features;
|
unsigned int features;
|
||||||
|
unsigned int quirks;
|
||||||
unsigned int num_crtcs;
|
unsigned int num_crtcs;
|
||||||
struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
|
struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
|
||||||
unsigned int num_lvds;
|
unsigned int num_lvds;
|
||||||
|
@ -84,6 +88,12 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu,
|
||||||
return rcdu->info->features & feature;
|
return rcdu->info->features & feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool rcar_du_needs(struct rcar_du_device *rcdu,
|
||||||
|
unsigned int quirk)
|
||||||
|
{
|
||||||
|
return rcdu->info->quirks & quirk;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
|
static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
|
||||||
{
|
{
|
||||||
return ioread32(rcdu->mmio + reg);
|
return ioread32(rcdu->mmio + reg);
|
||||||
|
|
|
@ -119,7 +119,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
|
||||||
/* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
|
/* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
|
||||||
* but the R8A7790 DU seems to require a 128 bytes pitch alignment.
|
* but the R8A7790 DU seems to require a 128 bytes pitch alignment.
|
||||||
*/
|
*/
|
||||||
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
|
if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
|
||||||
align = 128;
|
align = 128;
|
||||||
else
|
else
|
||||||
align = 16 * args->bpp / 8;
|
align = 16 * args->bpp / 8;
|
||||||
|
@ -144,7 +144,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
|
if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
|
||||||
align = 128;
|
align = 128;
|
||||||
else
|
else
|
||||||
align = 16 * format->bpp / 8;
|
align = 16 * format->bpp / 8;
|
||||||
|
|
|
@ -44,6 +44,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
|
||||||
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
|
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
|
||||||
unsigned int freq = mode->clock;
|
unsigned int freq = mode->clock;
|
||||||
u32 lvdcr0;
|
u32 lvdcr0;
|
||||||
|
u32 lvdhcr;
|
||||||
u32 pllcr;
|
u32 pllcr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -72,15 +73,19 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
|
||||||
* VSYNC -> CTRL1
|
* VSYNC -> CTRL1
|
||||||
* DISP -> CTRL2
|
* DISP -> CTRL2
|
||||||
* 0 -> CTRL3
|
* 0 -> CTRL3
|
||||||
*
|
|
||||||
* Channels 1 and 3 are switched on ES1.
|
|
||||||
*/
|
*/
|
||||||
rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
|
rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
|
||||||
LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
|
LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
|
||||||
LVDCTRCR_CTR0SEL_HSYNC);
|
LVDCTRCR_CTR0SEL_HSYNC);
|
||||||
rcar_lvds_write(lvds, LVDCHCR,
|
|
||||||
LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) |
|
if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
|
||||||
LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1));
|
lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
|
||||||
|
| LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
|
||||||
|
else
|
||||||
|
lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
|
||||||
|
| LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
|
||||||
|
|
||||||
|
rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
|
||||||
|
|
||||||
/* Select the input, hardcode mode 0, enable LVDS operation and turn
|
/* Select the input, hardcode mode 0, enable LVDS operation and turn
|
||||||
* bias circuitry on.
|
* bias circuitry on.
|
||||||
|
|
|
@ -104,6 +104,15 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
|
||||||
{
|
{
|
||||||
struct rcar_du_group *rgrp = plane->group;
|
struct rcar_du_group *rgrp = plane->group;
|
||||||
unsigned int index = plane->hwindex;
|
unsigned int index = plane->hwindex;
|
||||||
|
u32 mwr;
|
||||||
|
|
||||||
|
/* Memory pitch (expressed in pixels) */
|
||||||
|
if (plane->format->planes == 2)
|
||||||
|
mwr = plane->pitch;
|
||||||
|
else
|
||||||
|
mwr = plane->pitch * 8 / plane->format->bpp;
|
||||||
|
|
||||||
|
rcar_du_plane_write(rgrp, index, PnMWR, mwr);
|
||||||
|
|
||||||
/* The Y position is expressed in raster line units and must be doubled
|
/* The Y position is expressed in raster line units and must be doubled
|
||||||
* for 32bpp formats, according to the R8A7790 datasheet. No mention of
|
* for 32bpp formats, according to the R8A7790 datasheet. No mention of
|
||||||
|
@ -133,6 +142,8 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
|
||||||
{
|
{
|
||||||
struct drm_gem_cma_object *gem;
|
struct drm_gem_cma_object *gem;
|
||||||
|
|
||||||
|
plane->pitch = fb->pitches[0];
|
||||||
|
|
||||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||||
plane->dma[0] = gem->paddr + fb->offsets[0];
|
plane->dma[0] = gem->paddr + fb->offsets[0];
|
||||||
|
|
||||||
|
@ -209,7 +220,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
|
||||||
struct rcar_du_group *rgrp = plane->group;
|
struct rcar_du_group *rgrp = plane->group;
|
||||||
u32 ddcr2 = PnDDCR2_CODE;
|
u32 ddcr2 = PnDDCR2_CODE;
|
||||||
u32 ddcr4;
|
u32 ddcr4;
|
||||||
u32 mwr;
|
|
||||||
|
|
||||||
/* Data format
|
/* Data format
|
||||||
*
|
*
|
||||||
|
@ -240,14 +250,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
|
||||||
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
|
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
|
||||||
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
|
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
|
||||||
|
|
||||||
/* Memory pitch (expressed in pixels) */
|
|
||||||
if (plane->format->planes == 2)
|
|
||||||
mwr = plane->pitch;
|
|
||||||
else
|
|
||||||
mwr = plane->pitch * 8 / plane->format->bpp;
|
|
||||||
|
|
||||||
rcar_du_plane_write(rgrp, index, PnMWR, mwr);
|
|
||||||
|
|
||||||
/* Destination position and size */
|
/* Destination position and size */
|
||||||
rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
|
rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
|
||||||
rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
|
rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
|
||||||
|
@ -309,7 +311,6 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||||
|
|
||||||
rplane->crtc = crtc;
|
rplane->crtc = crtc;
|
||||||
rplane->format = format;
|
rplane->format = format;
|
||||||
rplane->pitch = fb->pitches[0];
|
|
||||||
|
|
||||||
rplane->src_x = src_x >> 16;
|
rplane->src_x = src_x >> 16;
|
||||||
rplane->src_y = src_y >> 16;
|
rplane->src_y = src_y >> 16;
|
||||||
|
|
Loading…
Add table
Reference in a new issue