mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
1737
drivers/gpu/drm/vc4/vc4_dsi.c
Normal file
1737
drivers/gpu/drm/vc4/vc4_dsi.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user