xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/drm_mipi_dsi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * MIPI DSI Bus
4  *
5  * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
6  * Andrzej Hajda <a.hajda@samsung.com>
7  */
8 
9 #include <drm/drm_mipi_dsi.h>
10 
11 #include <config.h>
12 #include <common.h>
13 #include <errno.h>
14 #include <malloc.h>
15 
16 /**
17  * mipi_dsi_attach - attach a DSI device to its DSI host
18  * @dsi: DSI peripheral
19  */
mipi_dsi_attach(struct mipi_dsi_device * dsi)20 int mipi_dsi_attach(struct mipi_dsi_device *dsi)
21 {
22 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
23 
24 	if (!ops || !ops->attach)
25 		return -ENOSYS;
26 
27 	return ops->attach(dsi->host, dsi);
28 }
29 
30 /**
31  * mipi_dsi_detach - detach a DSI device from its DSI host
32  * @dsi: DSI peripheral
33  */
mipi_dsi_detach(struct mipi_dsi_device * dsi)34 int mipi_dsi_detach(struct mipi_dsi_device *dsi)
35 {
36 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
37 
38 	if (!ops || !ops->detach)
39 		return -ENOSYS;
40 
41 	return ops->detach(dsi->host, dsi);
42 }
43 
mipi_dsi_device_transfer(struct mipi_dsi_device * dsi,struct mipi_dsi_msg * msg)44 static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
45 					struct mipi_dsi_msg *msg)
46 {
47 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
48 
49 	if (!ops || !ops->transfer)
50 		return -ENOSYS;
51 
52 	if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
53 		msg->flags |= MIPI_DSI_MSG_USE_LPM;
54 
55 	return ops->transfer(dsi->host, msg);
56 }
57 
58 /**
59  * mipi_dsi_packet_format_is_short - check if a packet is of the short format
60  * @type: MIPI DSI data type of the packet
61  *
62  * Return: true if the packet for the given data type is a short packet, false
63  * otherwise.
64  */
mipi_dsi_packet_format_is_short(u8 type)65 bool mipi_dsi_packet_format_is_short(u8 type)
66 {
67 	switch (type) {
68 	case MIPI_DSI_V_SYNC_START:
69 	case MIPI_DSI_V_SYNC_END:
70 	case MIPI_DSI_H_SYNC_START:
71 	case MIPI_DSI_H_SYNC_END:
72 	case MIPI_DSI_COMPRESSION_MODE:
73 	case MIPI_DSI_END_OF_TRANSMISSION:
74 	case MIPI_DSI_COLOR_MODE_OFF:
75 	case MIPI_DSI_COLOR_MODE_ON:
76 	case MIPI_DSI_SHUTDOWN_PERIPHERAL:
77 	case MIPI_DSI_TURN_ON_PERIPHERAL:
78 	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
79 	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
80 	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
81 	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
82 	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
83 	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
84 	case MIPI_DSI_DCS_SHORT_WRITE:
85 	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
86 	case MIPI_DSI_DCS_READ:
87 	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
88 		return true;
89 	}
90 
91 	return false;
92 }
93 
94 /**
95  * mipi_dsi_packet_format_is_long - check if a packet is of the long format
96  * @type: MIPI DSI data type of the packet
97  *
98  * Return: true if the packet for the given data type is a long packet, false
99  * otherwise.
100  */
mipi_dsi_packet_format_is_long(u8 type)101 bool mipi_dsi_packet_format_is_long(u8 type)
102 {
103 	switch (type) {
104 	case MIPI_DSI_NULL_PACKET:
105 	case MIPI_DSI_BLANKING_PACKET:
106 	case MIPI_DSI_GENERIC_LONG_WRITE:
107 	case MIPI_DSI_DCS_LONG_WRITE:
108 	case MIPI_DSI_PICTURE_PARAMETER_SET:
109 	case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
110 	case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
111 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
112 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
113 	case MIPI_DSI_PACKED_PIXEL_STREAM_30:
114 	case MIPI_DSI_PACKED_PIXEL_STREAM_36:
115 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
116 	case MIPI_DSI_PACKED_PIXEL_STREAM_16:
117 	case MIPI_DSI_PACKED_PIXEL_STREAM_18:
118 	case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
119 	case MIPI_DSI_PACKED_PIXEL_STREAM_24:
120 		return true;
121 	}
122 
123 	return false;
124 }
125 
126 /**
127  * mipi_dsi_create_packet - create a packet from a message according to the
128  *	DSI protocol
129  * @packet: pointer to a DSI packet structure
130  * @msg: message to translate into a packet
131  *
132  * Return: 0 on success or a negative error code on failure.
133  */
mipi_dsi_create_packet(struct mipi_dsi_packet * packet,const struct mipi_dsi_msg * msg)134 int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
135 			   const struct mipi_dsi_msg *msg)
136 {
137 	if (!packet || !msg)
138 		return -EINVAL;
139 
140 	/* do some minimum sanity checking */
141 	if (!mipi_dsi_packet_format_is_short(msg->type) &&
142 	    !mipi_dsi_packet_format_is_long(msg->type))
143 		return -EINVAL;
144 
145 	if (msg->channel > 3)
146 		return -EINVAL;
147 
148 	memset(packet, 0, sizeof(*packet));
149 	packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
150 	if (mipi_dsi_packet_format_is_long(msg->type)) {
151 		packet->header[1] = (msg->tx_len >> 0) & 0xff;
152 		packet->header[2] = (msg->tx_len >> 8) & 0xff;
153 
154 		packet->payload_length = msg->tx_len;
155 		packet->payload = msg->tx_buf;
156 	} else {
157 		const u8 *tx = msg->tx_buf;
158 
159 		packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
160 		packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
161 	}
162 
163 	packet->size = sizeof(packet->header) + packet->payload_length;
164 
165 	return 0;
166 }
167 
168 /**
169  * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
170  * @dsi: DSI peripheral device
171  *
172  * Return: 0 on success or a negative error code on failure.
173  */
mipi_dsi_shutdown_peripheral(struct mipi_dsi_device * dsi)174 int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
175 {
176 	struct mipi_dsi_msg msg = {
177 		.channel = dsi->channel,
178 		.type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
179 		.tx_buf = (u8 [2]) { 0, 0 },
180 		.tx_len = 2,
181 	};
182 	int ret = mipi_dsi_device_transfer(dsi, &msg);
183 
184 	return (ret < 0) ? ret : 0;
185 }
186 
187 /**
188  * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
189  * @dsi: DSI peripheral device
190  *
191  * Return: 0 on success or a negative error code on failure.
192  */
mipi_dsi_turn_on_peripheral(struct mipi_dsi_device * dsi)193 int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
194 {
195 	struct mipi_dsi_msg msg = {
196 		.channel = dsi->channel,
197 		.type = MIPI_DSI_TURN_ON_PERIPHERAL,
198 		.tx_buf = (u8 [2]) { 0, 0 },
199 		.tx_len = 2,
200 	};
201 	int ret = mipi_dsi_device_transfer(dsi, &msg);
202 
203 	return (ret < 0) ? ret : 0;
204 }
205 
206 /*
207  * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
208  *	the payload in a long packet transmitted from the peripheral back to the
209  *	host processor
210  * @dsi: DSI peripheral device
211  * @value: the maximum size of the payload
212  *
213  * Return: 0 on success or a negative error code on failure.
214  */
mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device * dsi,u16 value)215 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
216 					    u16 value)
217 {
218 	u8 tx[2] = { value & 0xff, value >> 8 };
219 	struct mipi_dsi_msg msg = {
220 		.channel = dsi->channel,
221 		.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
222 		.tx_len = sizeof(tx),
223 		.tx_buf = tx,
224 	};
225 	int ret = mipi_dsi_device_transfer(dsi, &msg);
226 
227 	return (ret < 0) ? ret : 0;
228 }
229 
230 /**
231  * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
232  * @dsi: DSI peripheral device
233  * @enable: Whether to enable or disable the DSC
234  *
235  * Enable or disable Display Stream Compression on the peripheral using the
236  * default Picture Parameter Set and VESA DSC 1.1 algorithm.
237  *
238  * Return: 0 on success or a negative error code on failure.
239  */
mipi_dsi_compression_mode(struct mipi_dsi_device * dsi,bool enable)240 ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
241 {
242 	/* Note: Needs updating for non-default PPS or algorithm */
243 	u8 tx[2] = { enable << 0, 0 };
244 	struct mipi_dsi_msg msg = {
245 		.channel = dsi->channel,
246 		.type = MIPI_DSI_COMPRESSION_MODE,
247 		.tx_len = sizeof(tx),
248 		.tx_buf = tx,
249 	};
250 	int ret = mipi_dsi_device_transfer(dsi, &msg);
251 
252 	return (ret < 0) ? ret : 0;
253 }
254 
255 /**
256  * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
257  * @dsi: DSI peripheral device
258  * @pps: VESA DSC 1.1 Picture Parameter Set
259  *
260  * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
261  *
262  * Return: 0 on success or a negative error code on failure.
263  */
mipi_dsi_picture_parameter_set(struct mipi_dsi_device * dsi,const struct drm_dsc_picture_parameter_set * pps)264 ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
265 				       const struct drm_dsc_picture_parameter_set *pps)
266 {
267 	struct mipi_dsi_msg msg = {
268 		.channel = dsi->channel,
269 		.type = MIPI_DSI_PICTURE_PARAMETER_SET,
270 		.tx_len = sizeof(*pps),
271 		.tx_buf = pps,
272 	};
273 	int ret = mipi_dsi_device_transfer(dsi, &msg);
274 
275 	return (ret < 0) ? ret : 0;
276 }
277 
278 /**
279  * mipi_dsi_generic_write() - transmit data using a generic write packet
280  * @dsi: DSI peripheral device
281  * @payload: buffer containing the payload
282  * @size: size of payload buffer
283  *
284  * This function will automatically choose the right data type depending on
285  * the payload length.
286  *
287  * Return: The number of bytes transmitted on success or a negative error code
288  * on failure.
289  */
mipi_dsi_generic_write(struct mipi_dsi_device * dsi,const void * payload,size_t size)290 ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
291 			       size_t size)
292 {
293 	struct mipi_dsi_msg msg = {
294 		.channel = dsi->channel,
295 		.tx_buf = payload,
296 		.tx_len = size
297 	};
298 
299 	switch (size) {
300 	case 0:
301 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
302 		break;
303 	case 1:
304 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
305 		break;
306 	case 2:
307 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
308 		break;
309 	default:
310 		msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
311 		break;
312 	}
313 
314 	return mipi_dsi_device_transfer(dsi, &msg);
315 }
316 
317 /**
318  * mipi_dsi_generic_read() - receive data using a generic read packet
319  * @dsi: DSI peripheral device
320  * @params: buffer containing the request parameters
321  * @num_params: number of request parameters
322  * @data: buffer in which to return the received data
323  * @size: size of receive buffer
324  *
325  * This function will automatically choose the right data type depending on
326  * the number of parameters passed in.
327  *
328  * Return: The number of bytes successfully read or a negative error code on
329  * failure.
330  */
mipi_dsi_generic_read(struct mipi_dsi_device * dsi,const void * params,size_t num_params,void * data,size_t size)331 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
332 			      size_t num_params, void *data, size_t size)
333 {
334 	struct mipi_dsi_msg msg = {
335 		.channel = dsi->channel,
336 		.tx_len = num_params,
337 		.tx_buf = params,
338 		.rx_len = size,
339 		.rx_buf = data
340 	};
341 
342 	switch (num_params) {
343 	case 0:
344 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
345 		break;
346 
347 	case 1:
348 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
349 		break;
350 
351 	case 2:
352 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
353 		break;
354 
355 	default:
356 		return -EINVAL;
357 	}
358 
359 	return mipi_dsi_device_transfer(dsi, &msg);
360 }
361 
362 /**
363  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
364  * @dsi: DSI peripheral device
365  * @data: buffer containing data to be transmitted
366  * @len: size of transmission buffer
367  *
368  * This function will automatically choose the right data type depending on
369  * the command payload length.
370  *
371  * Return: The number of bytes successfully transmitted or a negative error
372  * code on failure.
373  */
mipi_dsi_dcs_write_buffer(struct mipi_dsi_device * dsi,const void * data,size_t len)374 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
375 				  const void *data, size_t len)
376 {
377 	struct mipi_dsi_msg msg = {
378 		.channel = dsi->channel,
379 		.tx_buf = data,
380 		.tx_len = len
381 	};
382 
383 	switch (len) {
384 	case 0:
385 		return -EINVAL;
386 
387 	case 1:
388 		msg.type = MIPI_DSI_DCS_SHORT_WRITE;
389 		break;
390 
391 	case 2:
392 		msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
393 		break;
394 
395 	default:
396 		msg.type = MIPI_DSI_DCS_LONG_WRITE;
397 		break;
398 	}
399 
400 	return mipi_dsi_device_transfer(dsi, &msg);
401 }
402 
403 /**
404  * mipi_dsi_dcs_write() - send DCS write command
405  * @dsi: DSI peripheral device
406  * @cmd: DCS command
407  * @data: buffer containing the command payload
408  * @len: command payload length
409  *
410  * This function will automatically choose the right data type depending on
411  * the command payload length.
412  *
413  * Return: The number of bytes successfully transmitted or a negative error
414  * code on failure.
415  */
mipi_dsi_dcs_write(struct mipi_dsi_device * dsi,u8 cmd,const void * data,size_t len)416 ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
417 			   const void *data, size_t len)
418 {
419 	ssize_t err;
420 	size_t size;
421 	u8 *tx;
422 
423 	if (len > 0) {
424 		size = 1 + len;
425 
426 		tx = malloc(size);
427 		if (!tx)
428 			return -ENOMEM;
429 
430 		/* concatenate the DCS command byte and the payload */
431 		tx[0] = cmd;
432 		memcpy(&tx[1], data, len);
433 	} else {
434 		tx = &cmd;
435 		size = 1;
436 	}
437 
438 	err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
439 
440 	if (len > 0)
441 		free(tx);
442 
443 	return err;
444 }
445 
446 /**
447  * mipi_dsi_dcs_read() - send DCS read request command
448  * @dsi: DSI peripheral device
449  * @cmd: DCS command
450  * @data: buffer in which to receive data
451  * @len: size of receive buffer
452  * Return: The number of bytes read or a negative error code on failure.
453  */
mipi_dsi_dcs_read(struct mipi_dsi_device * dsi,u8 cmd,void * data,size_t len)454 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
455 			  size_t len)
456 {
457 	struct mipi_dsi_msg msg = {
458 		.channel = dsi->channel,
459 		.type = MIPI_DSI_DCS_READ,
460 		.tx_buf = &cmd,
461 		.tx_len = 1,
462 		.rx_buf = data,
463 		.rx_len = len
464 	};
465 
466 	return mipi_dsi_device_transfer(dsi, &msg);
467 }
468 
469 /**
470  * mipi_dsi_dcs_nop() - send DCS nop packet
471  * @dsi: DSI peripheral device
472  *
473  * Return: 0 on success or a negative error code on failure.
474  */
mipi_dsi_dcs_nop(struct mipi_dsi_device * dsi)475 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
476 {
477 	ssize_t err;
478 
479 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
480 	if (err < 0)
481 		return err;
482 
483 	return 0;
484 }
485 
486 /**
487  * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
488  * @dsi: DSI peripheral device
489  *
490  * Return: 0 on success or a negative error code on failure.
491  */
mipi_dsi_dcs_soft_reset(struct mipi_dsi_device * dsi)492 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
493 {
494 	ssize_t err;
495 
496 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
497 	if (err < 0)
498 		return err;
499 
500 	return 0;
501 }
502 
503 /**
504  * mipi_dsi_dcs_get_power_mode() - query the display module's current power
505  *	mode
506  * @dsi: DSI peripheral device
507  * @mode: return location for the current power mode
508  *
509  * Return: 0 on success or a negative error code on failure.
510  */
mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device * dsi,u8 * mode)511 int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
512 {
513 	ssize_t err;
514 
515 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
516 				sizeof(*mode));
517 	if (err <= 0) {
518 		if (err == 0)
519 			err = -ENODATA;
520 
521 		return err;
522 	}
523 
524 	return 0;
525 }
526 
527 /**
528  * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
529  *	data used by the interface
530  * @dsi: DSI peripheral device
531  * @format: return location for the pixel format
532  *
533  * Return: 0 on success or a negative error code on failure.
534  */
mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device * dsi,u8 * format)535 int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
536 {
537 	ssize_t err;
538 
539 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
540 				sizeof(*format));
541 	if (err <= 0) {
542 		if (err == 0)
543 			err = -ENODATA;
544 
545 		return err;
546 	}
547 
548 	return 0;
549 }
550 
551 /**
552  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
553  *	display module except interface communication
554  * @dsi: DSI peripheral device
555  *
556  * Return: 0 on success or a negative error code on failure.
557  */
mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device * dsi)558 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
559 {
560 	ssize_t err;
561 
562 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
563 	if (err < 0)
564 		return err;
565 
566 	return 0;
567 }
568 
569 /**
570  * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
571  *	module
572  * @dsi: DSI peripheral device
573  *
574  * Return: 0 on success or a negative error code on failure.
575  */
mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device * dsi)576 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
577 {
578 	ssize_t err;
579 
580 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
581 	if (err < 0)
582 		return err;
583 
584 	return 0;
585 }
586 
587 /**
588  * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
589  *	display device
590  * @dsi: DSI peripheral device
591  *
592  * Return: 0 on success or a negative error code on failure.
593  */
mipi_dsi_dcs_set_display_off(struct mipi_dsi_device * dsi)594 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
595 {
596 	ssize_t err;
597 
598 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
599 	if (err < 0)
600 		return err;
601 
602 	return 0;
603 }
604 
605 /**
606  * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
607  *	display device
608  * @dsi: DSI peripheral device
609  *
610  * Return: 0 on success or a negative error code on failure
611  */
mipi_dsi_dcs_set_display_on(struct mipi_dsi_device * dsi)612 int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
613 {
614 	ssize_t err;
615 
616 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
617 	if (err < 0)
618 		return err;
619 
620 	return 0;
621 }
622 
623 /**
624  * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
625  *	memory accessed by the host processor
626  * @dsi: DSI peripheral device
627  * @start: first column of frame memory
628  * @end: last column of frame memory
629  *
630  * Return: 0 on success or a negative error code on failure.
631  */
mipi_dsi_dcs_set_column_address(struct mipi_dsi_device * dsi,u16 start,u16 end)632 int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
633 				    u16 end)
634 {
635 	u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
636 	ssize_t err;
637 
638 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
639 				 sizeof(payload));
640 	if (err < 0)
641 		return err;
642 
643 	return 0;
644 }
645 
646 /**
647  * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
648  *	memory accessed by the host processor
649  * @dsi: DSI peripheral device
650  * @start: first page of frame memory
651  * @end: last page of frame memory
652  *
653  * Return: 0 on success or a negative error code on failure.
654  */
mipi_dsi_dcs_set_page_address(struct mipi_dsi_device * dsi,u16 start,u16 end)655 int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
656 				  u16 end)
657 {
658 	u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
659 	ssize_t err;
660 
661 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
662 				 sizeof(payload));
663 	if (err < 0)
664 		return err;
665 
666 	return 0;
667 }
668 
669 /**
670  * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
671  *	output signal on the TE signal line
672  * @dsi: DSI peripheral device
673  *
674  * Return: 0 on success or a negative error code on failure
675  */
mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device * dsi)676 int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
677 {
678 	ssize_t err;
679 
680 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
681 	if (err < 0)
682 		return err;
683 
684 	return 0;
685 }
686 
687 /**
688  * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
689  *	output signal on the TE signal line.
690  * @dsi: DSI peripheral device
691  * @mode: the Tearing Effect Output Line mode
692  *
693  * Return: 0 on success or a negative error code on failure
694  */
mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device * dsi,enum mipi_dsi_dcs_tear_mode mode)695 int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
696 			     enum mipi_dsi_dcs_tear_mode mode)
697 {
698 	u8 value = mode;
699 	ssize_t err;
700 
701 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
702 				 sizeof(value));
703 	if (err < 0)
704 		return err;
705 
706 	return 0;
707 }
708 
709 /**
710  * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
711  *	data used by the interface
712  * @dsi: DSI peripheral device
713  * @format: pixel format
714  *
715  * Return: 0 on success or a negative error code on failure.
716  */
mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device * dsi,u8 format)717 int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
718 {
719 	ssize_t err;
720 
721 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
722 				 sizeof(format));
723 	if (err < 0)
724 		return err;
725 
726 	return 0;
727 }
728 
729 /**
730  * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
731  *	the Tearing Effect output signal of the display module
732  * @dsi: DSI peripheral device
733  * @scanline: scanline to use as trigger
734  *
735  * Return: 0 on success or a negative error code on failure
736  */
mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device * dsi,u16 scanline)737 int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
738 {
739 	u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
740 				scanline & 0xff };
741 	ssize_t err;
742 
743 	err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
744 	if (err < 0)
745 		return err;
746 
747 	return 0;
748 }
749 
750 /**
751  * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
752  *	display
753  * @dsi: DSI peripheral device
754  * @brightness: brightness value
755  *
756  * Return: 0 on success or a negative error code on failure.
757  */
mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device * dsi,u16 brightness)758 int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
759 					u16 brightness)
760 {
761 	u8 payload[2] = { brightness & 0xff, brightness >> 8 };
762 	ssize_t err;
763 
764 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
765 				 payload, sizeof(payload));
766 	if (err < 0)
767 		return err;
768 
769 	return 0;
770 }
771 
772 /**
773  * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
774  *	of the display
775  * @dsi: DSI peripheral device
776  * @brightness: brightness value
777  *
778  * Return: 0 on success or a negative error code on failure.
779  */
mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device * dsi,u16 * brightness)780 int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
781 					u16 *brightness)
782 {
783 	ssize_t err;
784 
785 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
786 				brightness, sizeof(*brightness));
787 	if (err <= 0) {
788 		if (err == 0)
789 			err = -ENODATA;
790 
791 		return err;
792 	}
793 
794 	return 0;
795 }
796