Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2601a15d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-vc4-next-2016-12-09' of https://github.com/anholt/linux into drm-next

This pull request brings in VEC (TV-out) support for vc4, along with a
pageflipping race fix.

* tag 'drm-vc4-next-2016-12-09' of https://github.com/anholt/linux:
  drm/vc4: Don't use drm_put_dev
  drm/vc4: Document VEC DT binding
  drm/vc4: Add support for the VEC (Video Encoder) IP
  drm: Add TV connector states to drm_connector_state
  drm: Turn DRM_MODE_SUBCONNECTOR_xx definitions into an enum
  drm/vc4: Fix ->clock_select setting for the VEC encoder
  drm/vc4: Fix race between page flip completion event and clean-up
parents 25dfd7cf c167df44
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -43,6 +43,13 @@ Required properties for DPI:
- port:		Port node with a single endpoint connecting to the panel
		  device, as defined in [1]

Required properties for VEC:
- compatible:	Should be "brcm,bcm2835-vec"
- reg:		Physical base address and length of the registers
- clocks:	The core clock the unit runs on
- interrupts:	The interrupt number
		  See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt

Required properties for V3D:
- compatible:	Should be "brcm,bcm2835-v3d"
- reg:		Physical base address and length of the V3D's registers
@@ -92,6 +99,13 @@ dpi: dpi@7e208000 {
	};
};

vec: vec@7e806000 {
	compatible = "brcm,bcm2835-vec";
	reg = <0x7e806000 0x1000>;
	clocks = <&clocks BCM2835_CLOCK_VEC>;
	interrupts = <2 27>;
};

v3d: v3d@7ec00000 {
	compatible = "brcm,bcm2835-v3d";
	reg = <0x7ec00000 0x1000>;
+50 −0
Original line number Diff line number Diff line
@@ -1087,12 +1087,38 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
		 * now?) atomic writes to DPMS property:
		 */
		return -EINVAL;
	} else if (property == config->tv_select_subconnector_property) {
		state->tv.subconnector = val;
	} else if (property == config->tv_left_margin_property) {
		state->tv.margins.left = val;
	} else if (property == config->tv_right_margin_property) {
		state->tv.margins.right = val;
	} else if (property == config->tv_top_margin_property) {
		state->tv.margins.top = val;
	} else if (property == config->tv_bottom_margin_property) {
		state->tv.margins.bottom = val;
	} else if (property == config->tv_mode_property) {
		state->tv.mode = val;
	} else if (property == config->tv_brightness_property) {
		state->tv.brightness = val;
	} else if (property == config->tv_contrast_property) {
		state->tv.contrast = val;
	} else if (property == config->tv_flicker_reduction_property) {
		state->tv.flicker_reduction = val;
	} else if (property == config->tv_overscan_property) {
		state->tv.overscan = val;
	} else if (property == config->tv_saturation_property) {
		state->tv.saturation = val;
	} else if (property == config->tv_hue_property) {
		state->tv.hue = val;
	} else if (connector->funcs->atomic_set_property) {
		return connector->funcs->atomic_set_property(connector,
				state, property, val);
	} else {
		return -EINVAL;
	}

	return 0;
}
EXPORT_SYMBOL(drm_atomic_connector_set_property);

@@ -1135,6 +1161,30 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
		*val = (state->crtc) ? state->crtc->base.id : 0;
	} else if (property == config->dpms_property) {
		*val = connector->dpms;
	} else if (property == config->tv_select_subconnector_property) {
		*val = state->tv.subconnector;
	} else if (property == config->tv_left_margin_property) {
		*val = state->tv.margins.left;
	} else if (property == config->tv_right_margin_property) {
		*val = state->tv.margins.right;
	} else if (property == config->tv_top_margin_property) {
		*val = state->tv.margins.top;
	} else if (property == config->tv_bottom_margin_property) {
		*val = state->tv.margins.bottom;
	} else if (property == config->tv_mode_property) {
		*val = state->tv.mode;
	} else if (property == config->tv_brightness_property) {
		*val = state->tv.brightness;
	} else if (property == config->tv_contrast_property) {
		*val = state->tv.contrast;
	} else if (property == config->tv_flicker_reduction_property) {
		*val = state->tv.flicker_reduction;
	} else if (property == config->tv_overscan_property) {
		*val = state->tv.overscan;
	} else if (property == config->tv_saturation_property) {
		*val = state->tv.saturation;
	} else if (property == config->tv_hue_property) {
		*val = state->tv.hue;
	} else if (connector->funcs->atomic_get_property) {
		return connector->funcs->atomic_get_property(connector,
				state, property, val);
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ vc4-y := \
	vc4_kms.o \
	vc4_gem.o \
	vc4_hdmi.o \
	vc4_vec.o \
	vc4_hvs.o \
	vc4_irq.o \
	vc4_plane.o \
+31 −15
Original line number Diff line number Diff line
@@ -83,8 +83,7 @@ struct vc4_crtc_data {
	/* Which channel of the HVS this pixelvalve sources from. */
	int hvs_channel;

	enum vc4_encoder_type encoder0_type;
	enum vc4_encoder_type encoder1_type;
	enum vc4_encoder_type encoder_types[4];
};

#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
@@ -669,6 +668,14 @@ void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
	CRTC_WRITE(PV_INTEN, 0);
}

/* Must be called with the event lock held */
bool vc4_event_pending(struct drm_crtc *crtc)
{
	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);

	return !!vc4_crtc->event;
}

static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
{
	struct drm_crtc *crtc = &vc4_crtc->base;
@@ -859,20 +866,26 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {

static const struct vc4_crtc_data pv0_data = {
	.hvs_channel = 0,
	.encoder0_type = VC4_ENCODER_TYPE_DSI0,
	.encoder1_type = VC4_ENCODER_TYPE_DPI,
	.encoder_types = {
		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
	},
};

static const struct vc4_crtc_data pv1_data = {
	.hvs_channel = 2,
	.encoder0_type = VC4_ENCODER_TYPE_DSI1,
	.encoder1_type = VC4_ENCODER_TYPE_SMI,
	.encoder_types = {
		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
	},
};

static const struct vc4_crtc_data pv2_data = {
	.hvs_channel = 1,
	.encoder0_type = VC4_ENCODER_TYPE_VEC,
	.encoder1_type = VC4_ENCODER_TYPE_HDMI,
	.encoder_types = {
		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
	},
};

static const struct of_device_id vc4_crtc_dt_match[] = {
@@ -886,17 +899,20 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
					struct drm_crtc *crtc)
{
	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
	const struct vc4_crtc_data *crtc_data = vc4_crtc->data;
	const enum vc4_encoder_type *encoder_types = crtc_data->encoder_types;
	struct drm_encoder *encoder;

	drm_for_each_encoder(encoder, drm) {
		struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
		int i;

		if (vc4_encoder->type == vc4_crtc->data->encoder0_type) {
			vc4_encoder->clock_select = 0;
			encoder->possible_crtcs |= drm_crtc_mask(crtc);
		} else if (vc4_encoder->type == vc4_crtc->data->encoder1_type) {
			vc4_encoder->clock_select = 1;
		for (i = 0; i < ARRAY_SIZE(crtc_data->encoder_types); i++) {
			if (vc4_encoder->type == encoder_types[i]) {
				vc4_encoder->clock_select = i;
				encoder->possible_crtcs |= drm_crtc_mask(crtc);
				break;
			}
		}
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,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},
	{"vec_regs", vc4_vec_debugfs_regs, 0},
	{"hvs_regs", vc4_hvs_debugfs_regs, 0},
	{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
	{"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
Loading