aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/dispsys/mt6735/ddp_met.c
blob: b2106b1a9a36970cd703d09dabf080ed273486a8 (plain) (blame)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#define LOG_TAG "MET" 

#include "ddp_log.h"

#include <linux/met_drv.h>
#include "ddp_irq.h"
#include "ddp_reg.h"
#include "ddp_met.h"
#include "ddp_ovl.h"
#include "ddp_rdma.h"

#define DDP_IRQ_EER_ID 				(0xFFFF0000)
#define DDP_IRQ_FPS_ID 				(DDP_IRQ_EER_ID + 1)
#define DDP_IRQ_LAYER_FPS_ID 		(DDP_IRQ_EER_ID + 2)
#define DDP_IRQ_LAYER_SIZE_ID 		(DDP_IRQ_EER_ID + 3)
#define DDP_IRQ_LAYER_FORMAT_ID 	(DDP_IRQ_EER_ID + 4)

#define MAX_PATH_NUM (3)
#define OVL_NUM (2)
#define RDMA_NUM (3)
#define MAX_OVL_LAYERS (4)

unsigned int met_tag_on = 0;

static const char* const parse_color_format(DpColorFormat fmt) {
	switch (fmt) {
	case eBGR565:
		return "eBGR565";
	case eRGB565:
		return "eRGB565";
	case eRGB888:
		return "eRGB888";
	case eBGR888:
		return "eBGR888";
	case eRGBA8888:
		return "eRGBA8888";
	case eBGRA8888:
		return "eBGRA8888";
	case eARGB8888:
		return "eARGB8888";
	case eABGR8888:
		return "eABGR8888";
	case eVYUY:
		return "eVYUY";
	case eUYVY:
		return "eUYVY";
	case eYVYU:
		return "eYVYU";
	case eYUY2:
		return "eYUY2";
	}
}

/**
 * Represent to LCM display refresh rate
 * Primary Display:  map to RDMA0 sof/eof ISR, for all display mode
 * External Display: map to RDMA1 sof/eof ISR, for all display mode
 * NOTICE:
 * 		for WFD, nothing we can do here
 */
static void ddp_disp_refresh_tag_start(unsigned int index) {
	static unsigned long sBufAddr[RDMA_NUM];
	static RDMA_BASIC_STRUCT rdmaInfo;
	char tag_name[30] = { '\0' };
	rdma_get_info(index, &rdmaInfo);
	if (rdmaInfo.addr == 0 || (rdmaInfo.addr != 0 && sBufAddr[index] != rdmaInfo.addr)) {
		sBufAddr[index] = rdmaInfo.addr;
		sprintf(tag_name, index ? "ExtDispRefresh" : "PrimDispRefresh");
		met_tag_oneshot(DDP_IRQ_FPS_ID, tag_name, 1);
	}
}

static void ddp_disp_refresh_tag_end(unsigned int index) {
	char tag_name[30] = { '\0' };
	sprintf(tag_name, index ? "ExtDispRefresh" : "PrimDispRefresh");
	met_tag_oneshot(DDP_IRQ_FPS_ID, tag_name, 0);
}

/**
 * Represent to OVL0/0VL1 each layer's refresh rate
 */
static void ddp_inout_info_tag(unsigned int index) {
	static unsigned long sLayerBufAddr[OVL_NUM][OVL_LAYER_NUM_PER_OVL];
	static unsigned int  sLayerBufFmt[OVL_NUM][OVL_LAYER_NUM_PER_OVL];
	static unsigned int  sLayerBufWidth[OVL_NUM][OVL_LAYER_NUM_PER_OVL];
	static unsigned int  sLayerBufHeight[OVL_NUM][OVL_LAYER_NUM_PER_OVL];

	OVL_BASIC_STRUCT ovlInfo[OVL_LAYER_NUM];
	unsigned int flag, i, idx, enLayerCnt, layerCnt;
	unsigned int width, height, bpp, fmt;
	char* fmtStr;
	char tag_name[30] = { '\0' };
	memset((void*)ovlInfo, 0, sizeof(ovlInfo));
	ovl_get_info(index, ovlInfo);

	//Any layer enable bit changes , new frame refreshes
	enLayerCnt = 0;
	if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
		layerCnt = OVL_LAYER_NUM;
	} else {
		layerCnt = OVL_LAYER_NUM_PER_OVL;
	}

	for (i = 0; i < layerCnt; i++) {
		if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
			index = 1 - i / OVL_LAYER_NUM_PER_OVL;
		}
		idx = i % OVL_LAYER_NUM_PER_OVL;

		fmtStr = parse_color_format(ovlInfo[i].fmt);

		if (ovlInfo[i].layer_en) {
			enLayerCnt++;
			if (sLayerBufAddr[index][idx] != ovlInfo[i].addr) {
				sLayerBufAddr[index][idx] = ovlInfo[i].addr;
				sprintf(tag_name, "OVL%dL%d_InFps", index, idx);
				met_tag_oneshot(DDP_IRQ_LAYER_FPS_ID, tag_name, i+1);
			}
			if (sLayerBufFmt[index][idx] != ovlInfo[i].fmt) {
				sLayerBufFmt[index][idx] = ovlInfo[i].fmt;
				sprintf(tag_name, "OVL%dL%d_Fmt_%s", index, idx, fmtStr);
				met_tag_oneshot(DDP_IRQ_LAYER_FORMAT_ID, tag_name, i+1);
			}
			if (sLayerBufWidth[index][idx] != ovlInfo[i].src_w) {
				sLayerBufWidth[index][idx] = ovlInfo[i].src_w;
				sprintf(tag_name, "OVL%dL%d_Width", index, idx);
				met_tag_oneshot(DDP_IRQ_LAYER_SIZE_ID, tag_name, ovlInfo[i].src_w);
			}
			if (sLayerBufHeight[index][idx] != ovlInfo[i].src_h) {
				sLayerBufHeight[index][idx] = ovlInfo[i].src_h;
				sprintf(tag_name, "OVL%dL%d_Height", index, idx);
				met_tag_oneshot(DDP_IRQ_LAYER_SIZE_ID, tag_name, ovlInfo[i].src_h);
			}

		} else {
			sLayerBufAddr[index][idx] = 0;
			sLayerBufFmt[index][idx] = 0;
			sLayerBufWidth[index][idx] = 0;
			sLayerBufHeight[index][idx] = 0;
		}

		if ( (i == (OVL_LAYER_NUM_PER_OVL-1)) || (i == (OVL_LAYER_NUM-1)) ) {
			if (enLayerCnt) {
				enLayerCnt = 0;
				sprintf(tag_name, "OVL%d_OutFps", index);
				met_tag_oneshot(DDP_IRQ_LAYER_FPS_ID, tag_name, index);
			}
		}
	}

}

static void ddp_err_irq_met_tag(const char *name) {
	met_tag_oneshot(DDP_IRQ_EER_ID, name, 0);
	return;
}

static void met_irq_handler(DISP_MODULE_ENUM module, unsigned int reg_val) {
	int index = 0;
	char tag_name[30] = { '\0' };
	//DDPERR("met_irq_handler() module=%d, val=0x%x \n", module, reg_val);
	switch (module) {
	case DISP_MODULE_RDMA0:
	case DISP_MODULE_RDMA1:
		index = module - DISP_MODULE_RDMA0;
		if (reg_val & (1 << 2)) {
			ddp_disp_refresh_tag_end(index);
		}
		if (reg_val & (1 << 1)) {
			ddp_disp_refresh_tag_start(index);
		}
		if (reg_val & (1 << 4)) {
			sprintf(tag_name, "rdma%d_underflow", index);
			ddp_err_irq_met_tag(tag_name);
		}
		if (reg_val & (1 << 3)) {
			sprintf(tag_name, "rdma%d_abnormal", index);
			ddp_err_irq_met_tag(tag_name);
		}
		break;

	case DISP_MODULE_OVL0:
	case DISP_MODULE_OVL1:
		index = module - DISP_MODULE_OVL0;
		if (reg_val & (1 << 1)) {
			ddp_inout_info_tag(index);
		}
		break;
	default:
		break;
	}
	return;
}

void ddp_init_met_tag(int state, int rdma0_mode, int rdma1_mode) {
	if ((!met_tag_on) && state) {
		met_tag_on = state;
		disp_register_irq_callback(met_irq_handler);
	}
	if (met_tag_on && (!state)) {
		met_tag_on = state;
		disp_unregister_irq_callback(met_irq_handler);
	}
}