drm/vc4: Add DSI1 driver

The DSI0 and DSI1 blocks on the 2835 are different but very similar
hardware blocks.  Some registers move around, and the featureset is
slightly different, but they're clearly related.  This doesn't enable
DSI0, but some of the infrastructure is present.

Also, this driver doesn't initialize the DSI successfully from
poweron, so we currently require that the Raspberry Pi firmware enable
it at boot time.  From there, we just keep the same settings forever,
and when poweroff is requested we just scan out black instead.

Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Eric Anholt
2016-02-10 11:42:32 -08:00
parent 315305371b
commit 4fd3807517
7 changed files with 1780 additions and 12 deletions

View File

@@ -6,6 +6,8 @@ config DRM_VC4
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
select CLKSRC_OF
help
Choose this option if you have a system that has a Broadcom
VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835.

View File

@@ -8,6 +8,7 @@ vc4-y := \
vc4_crtc.o \
vc4_drv.o \
vc4_dpi.o \
vc4_dsi.o \
vc4_kms.o \
vc4_gem.o \
vc4_hdmi.o \

View File

@@ -231,7 +231,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
bool debug_dump_regs = true;
bool debug_dump_regs = false;
if (debug_dump_regs) {
DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
@@ -327,6 +327,19 @@ static void vc4_crtc_disable(struct drm_crtc *crtc)
int ret;
require_hvs_enabled(dev);
if (VC4_DSI_USE_FIRMWARE_SETUP &&
(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_DSI)) {
/* Skip disabling the PV/HVS for the channel if it was
* connected to the DSI panel and we're using the
* firmware setup. Instead, just set it to stuff
* black in the composite output buffer.
*/
HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
SCALER_DISPBKGND_FILL);
return;
}
CRTC_WRITE(PV_V_CONTROL,
CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
@@ -396,17 +409,19 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
if (drm_atomic_connectors_for_crtc(state->state, crtc) > 1)
return -EINVAL;
drm_atomic_crtc_state_for_each_plane(plane, state) {
struct drm_plane_state *plane_state =
state->state->plane_states[drm_plane_index(plane)];
if (state->active) {
drm_atomic_crtc_state_for_each_plane(plane, state) {
struct drm_plane_state *plane_state =
state->state->plane_states[drm_plane_index(plane)];
/* plane might not have changed, in which case take
* current state:
*/
if (!plane_state)
plane_state = plane->state;
/* plane might not have changed, in which case take
* current state:
*/
if (!plane_state)
plane_state = plane->state;
dlist_count += vc4_plane_dlist_size(plane_state);
dlist_count += vc4_plane_dlist_size(plane_state);
}
}
dlist_count++; /* Account for SCALER_CTL0_END. */
@@ -439,8 +454,10 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
}
/* Copy all the active planes' dlist contents to the hardware dlist. */
drm_atomic_crtc_for_each_plane(plane, crtc) {
dlist_next += vc4_plane_write_dlist(plane, dlist_next);
if (crtc->state->active) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
dlist_next += vc4_plane_write_dlist(plane, dlist_next);
}
}
writel(SCALER_CTL0_END, dlist_next);

View File

@@ -19,6 +19,8 @@ static const struct drm_info_list vc4_debugfs_list[] = {
{"bo_stats", vc4_bo_stats_debugfs, 0},
{"dpi_regs", vc4_dpi_debugfs_regs, 0},
{"gem_exec", vc4_gem_exec_debugfs, 0},
{"dsi0_regs", vc4_dsi_debugfs_regs, 0, (void *)(uintptr_t)0},
{"dsi1_regs", vc4_dsi_debugfs_regs, 0, (void *)(uintptr_t)1},
{"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
{"hvs_regs", vc4_hvs_debugfs_regs, 0},
{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},

View File

@@ -294,6 +294,7 @@ static const struct component_master_ops vc4_drm_ops = {
static struct platform_driver *const component_drivers[] = {
&vc4_hdmi_driver,
&vc4_dpi_driver,
&vc4_dsi_driver,
&vc4_crtc_driver,
&vc4_hvs_driver,
&vc4_v3d_driver,

View File

@@ -19,6 +19,8 @@ struct vc4_dev {
struct vc4_crtc *crtc[3];
struct vc4_v3d *v3d;
struct vc4_dpi *dpi;
struct vc4_dsi *dsi0;
struct vc4_dsi *dsi1;
struct drm_fbdev_cma *fbdev;
struct rpi_firmware *firmware;
@@ -192,6 +194,8 @@ enum vc4_encoder_type {
VC4_ENCODER_TYPE_DPI,
};
#define VC4_DSI_USE_FIRMWARE_SETUP true
struct vc4_encoder {
struct drm_encoder base;
enum vc4_encoder_type type;
@@ -429,6 +433,10 @@ void vc4_dump_regs32(const struct debugfs_reg32 *reg, unsigned int num_regs,
extern struct platform_driver vc4_dpi_driver;
int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused);
/* vc4_dsi.c */
extern struct platform_driver vc4_dsi_driver;
int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused);
/* vc4_gem.c */
void vc4_gem_init(struct drm_device *dev);
void vc4_gem_destroy(struct drm_device *dev);

File diff suppressed because it is too large Load Diff