Skip to content

Commit

Permalink
Merge tag 'drm-vc4-next-2016-05-02' of https://github.com/anholt/linux
Browse files Browse the repository at this point in the history
…into drm-next

This pull request brings in DPI panel support, gamma ramp support, and
render nodes for vc4.

* tag 'drm-vc4-next-2016-05-02' of https://github.com/anholt/linux:
  drm/vc4: Add missing render node support
  drm/vc4: Add support for gamma ramps.
  drm/vc4: Fix NULL deref in HDMI init error path
  drm/vc4: Add DPI driver
  drm: Add an encoder and connector type enum for DPI.
  • Loading branch information
Dave Airlie committed May 4, 2016
2 parents 2b8f01f + 0cd3e27 commit acff058
Show file tree
Hide file tree
Showing 12 changed files with 635 additions and 1 deletion.
36 changes: 36 additions & 0 deletions Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,22 @@ Optional properties for HDMI:
as an interrupt/status bit in the HDMI controller
itself). See bindings/pinctrl/brcm,bcm2835-gpio.txt

Required properties for DPI:
- compatible: Should be "brcm,bcm2835-dpi"
- reg: Physical base address and length of the registers
- clocks: a) core: The core clock the unit runs on
b) pixel: The pixel clock that feeds the pixelvalve
- port: Port node with a single endpoint connecting to the panel
device, as defined in [1]

Required properties for V3D:
- compatible: Should be "brcm,bcm2835-v3d"
- reg: Physical base address and length of the V3D's registers
- interrupts: The interrupt number
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt

[1] Documentation/devicetree/bindings/media/video-interfaces.txt

Example:
pixelvalve@7e807000 {
compatible = "brcm,bcm2835-pixelvalve2";
Expand All @@ -66,6 +76,22 @@ hdmi: hdmi@7e902000 {
clock-names = "pixel", "hdmi";
};

dpi: dpi@7e208000 {
compatible = "brcm,bcm2835-dpi";
reg = <0x7e208000 0x8c>;
clocks = <&clocks BCM2835_CLOCK_VPU>,
<&clocks BCM2835_CLOCK_DPI>;
clock-names = "core", "pixel";
#address-cells = <1>;
#size-cells = <0>;

port {
dpi_out: endpoint@0 {
remote-endpoint = <&panel_in>;
};
};
};

v3d: v3d@7ec00000 {
compatible = "brcm,bcm2835-v3d";
reg = <0x7ec00000 0x1000>;
Expand All @@ -75,3 +101,13 @@ v3d: v3d@7ec00000 {
vc4: gpu {
compatible = "brcm,bcm2835-vc4";
};

panel: panel {
compatible = "ontat,yx700wv03", "simple-panel";

port {
panel_in: endpoint {
remote-endpoint = <&dpi_out>;
};
};
};
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
{ DRM_MODE_CONNECTOR_eDP, "eDP" },
{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
{ DRM_MODE_CONNECTOR_DSI, "DSI" },
{ DRM_MODE_CONNECTOR_DPI, "DPI" },
};

static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
Expand All @@ -179,6 +180,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
{ DRM_MODE_ENCODER_DSI, "DSI" },
{ DRM_MODE_ENCODER_DPMST, "DP MST" },
{ DRM_MODE_ENCODER_DPI, "DPI" },
};

static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/vc4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ config DRM_VC4
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select DRM_PANEL
help
Choose this option if you have a system that has a Broadcom
VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835.
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/vc4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ vc4-y := \
vc4_bo.o \
vc4_crtc.o \
vc4_drv.o \
vc4_dpi.o \
vc4_kms.o \
vc4_gem.o \
vc4_hdmi.o \
Expand Down
58 changes: 58 additions & 0 deletions drivers/gpu/drm/vc4/vc4_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ struct vc4_crtc {
/* Which HVS channel we're using for our CRTC. */
int channel;

u8 lut_r[256];
u8 lut_g[256];
u8 lut_b[256];

struct drm_pending_vblank_event *event;
};

Expand Down Expand Up @@ -147,6 +151,46 @@ static void vc4_crtc_destroy(struct drm_crtc *crtc)
drm_crtc_cleanup(crtc);
}

static void
vc4_crtc_lut_load(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
u32 i;

/* The LUT memory is laid out with each HVS channel in order,
* each of which takes 256 writes for R, 256 for G, then 256
* for B.
*/
HVS_WRITE(SCALER_GAMADDR,
SCALER_GAMADDR_AUTOINC |
(vc4_crtc->channel * 3 * crtc->gamma_size));

for (i = 0; i < crtc->gamma_size; i++)
HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
for (i = 0; i < crtc->gamma_size; i++)
HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
for (i = 0; i < crtc->gamma_size; i++)
HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
}

static void
vc4_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
uint32_t start, uint32_t size)
{
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
u32 i;

for (i = start; i < start + size; i++) {
vc4_crtc->lut_r[i] = r[i] >> 8;
vc4_crtc->lut_g[i] = g[i] >> 8;
vc4_crtc->lut_b[i] = b[i] >> 8;
}

vc4_crtc_lut_load(crtc);
}

static u32 vc4_get_fifo_full_level(u32 format)
{
static const u32 fifo_len_bytes = 64;
Expand Down Expand Up @@ -260,8 +304,14 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)

HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
SCALER_DISPBKGND_AUTOHS |
SCALER_DISPBKGND_GAMMA |
(interlace ? SCALER_DISPBKGND_INTERLACE : 0));

/* Reload the LUT, since the SRAMs would have been disabled if
* all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
*/
vc4_crtc_lut_load(crtc);

if (debug_dump_regs) {
DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
vc4_crtc_dump_regs(vc4_crtc);
Expand Down Expand Up @@ -613,6 +663,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = vc4_crtc_duplicate_state,
.atomic_destroy_state = vc4_crtc_destroy_state,
.gamma_set = vc4_crtc_gamma_set,
};

static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
Expand Down Expand Up @@ -711,6 +762,7 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
primary_plane->crtc = crtc;
vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc;
vc4_crtc->channel = vc4_crtc->data->hvs_channel;
drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));

/* Set up some arbitrary number of planes. We're not limited
* by a set number of physical registers, just the space in
Expand Down Expand Up @@ -751,6 +803,12 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)

vc4_set_crtc_possible_masks(drm, crtc);

for (i = 0; i < crtc->gamma_size; i++) {
vc4_crtc->lut_r[i] = i;
vc4_crtc->lut_g[i] = i;
vc4_crtc->lut_b[i] = i;
}

platform_set_drvdata(pdev, vc4_crtc);

return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/vc4/vc4_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

static const struct drm_info_list vc4_debugfs_list[] = {
{"bo_stats", vc4_bo_stats_debugfs, 0},
{"dpi_regs", vc4_dpi_debugfs_regs, 0},
{"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},
Expand Down
Loading

0 comments on commit acff058

Please sign in to comment.