summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sti/sti_vid.c
blob: 10ced6a479f42fb8cb1235a7409ad336097894ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Copyright (C) STMicroelectronics SA 2014
 * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
 * License terms:  GNU General Public License (GPL), version 2
 */

#include <drm/drmP.h>

#include "sti_layer.h"
#include "sti_vid.h"
#include "sti_vtg.h"

/* Registers */
#define VID_CTL                 0x00
#define VID_ALP                 0x04
#define VID_CLF                 0x08
#define VID_VPO                 0x0C
#define VID_VPS                 0x10
#define VID_KEY1                0x28
#define VID_KEY2                0x2C
#define VID_MPR0                0x30
#define VID_MPR1                0x34
#define VID_MPR2                0x38
#define VID_MPR3                0x3C
#define VID_MST                 0x68
#define VID_BC                  0x70
#define VID_TINT                0x74
#define VID_CSAT                0x78

/* Registers values */
#define VID_CTL_IGNORE          (BIT(31) | BIT(30))
#define VID_CTL_PSI_ENABLE      (BIT(2) | BIT(1) | BIT(0))
#define VID_ALP_OPAQUE          0x00000080
#define VID_BC_DFLT             0x00008000
#define VID_TINT_DFLT           0x00000000
#define VID_CSAT_DFLT           0x00000080
/* YCbCr to RGB BT709:
 * R = Y+1.5391Cr
 * G = Y-0.4590Cr-0.1826Cb
 * B = Y+1.8125Cb */
#define VID_MPR0_BT709          0x0A800000
#define VID_MPR1_BT709          0x0AC50000
#define VID_MPR2_BT709          0x07150545
#define VID_MPR3_BT709          0x00000AE8

static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
{
	u32 val;

	/* Unmask */
	val = readl(vid->regs + VID_CTL);
	val &= ~VID_CTL_IGNORE;
	writel(val, vid->regs + VID_CTL);

	return 0;
}

static int sti_vid_commit_layer(struct sti_layer *vid)
{
	struct drm_display_mode *mode = vid->mode;
	u32 ydo, xdo, yds, xds;

	ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
	yds = sti_vtg_get_line_number(*mode, vid->dst_y + vid->dst_h - 1);
	xdo = sti_vtg_get_pixel_number(*mode, vid->dst_x);
	xds = sti_vtg_get_pixel_number(*mode, vid->dst_x + vid->dst_w - 1);

	writel((ydo << 16) | xdo, vid->regs + VID_VPO);
	writel((yds << 16) | xds, vid->regs + VID_VPS);

	return 0;
}

static int sti_vid_disable_layer(struct sti_layer *vid)
{
	u32 val;

	/* Mask */
	val = readl(vid->regs + VID_CTL);
	val |= VID_CTL_IGNORE;
	writel(val, vid->regs + VID_CTL);

	return 0;
}

static const uint32_t *sti_vid_get_formats(struct sti_layer *layer)
{
	return NULL;
}

static unsigned int sti_vid_get_nb_formats(struct sti_layer *layer)
{
	return 0;
}

static void sti_vid_init(struct sti_layer *vid)
{
	/* Enable PSI, Mask layer */
	writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);

	/* Opaque */
	writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);

	/* Color conversion parameters */
	writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
	writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
	writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
	writel(VID_MPR3_BT709, vid->regs + VID_MPR3);

	/* Brightness, contrast, tint, saturation */
	writel(VID_BC_DFLT, vid->regs + VID_BC);
	writel(VID_TINT_DFLT, vid->regs + VID_TINT);
	writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
}

static const struct sti_layer_funcs vid_ops = {
	.get_formats = sti_vid_get_formats,
	.get_nb_formats = sti_vid_get_nb_formats,
	.init = sti_vid_init,
	.prepare = sti_vid_prepare_layer,
	.commit = sti_vid_commit_layer,
	.disable = sti_vid_disable_layer,
};

struct sti_layer *sti_vid_create(struct device *dev)
{
	struct sti_layer *vid;

	vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
	if (!vid) {
		DRM_ERROR("Failed to allocate memory for VID\n");
		return NULL;
	}

	vid->ops = &vid_ops;

	return vid;
}