2 #include "mipi_dsih_api.h"
\r
3 #include "mipi_dsih_hal.h"
\r
4 #include "mipi_dsih_dphy.h"
\r
5 /* whether to get debug messages (1) or not (0) */
\r
8 #define PRECISION_FACTOR 1000
\r
9 #define VIDEO_PACKET_OVERHEAD 6
\r
10 #define NULL_PACKET_OVERHEAD 6
\r
11 #define SHORT_PACKET 4
\r
12 #define BLANKING_PACKET 6
\r
13 #define MAX_NULL_SIZE 1023
\r
15 static const uint32_t mipi_dsih_supported_versions[] = {0x3130302A, 0x3130312A, 0x3131302A};
\r
16 static const uint32_t mipi_dsih_no_of_versions = sizeof(mipi_dsih_supported_versions) / sizeof(uint32_t);
\r
20 func:mipi_dsih_set_lp_clock
\r
21 desc:in low-power mode, max PHY frequency should smaller than 20MHz,
\r
22 in synopsys IP, low-power clock divide from high-speed clock,
\r
23 this function is designed to adapt low-power clock to various high-speed clock.
\r
25 Fhs : high-speed frequence
\r
26 Flp : low-power frequence
\r
27 div : mipi_dsih_hal_tx_escape_division() param, byte clock unit.
\r
28 because of the 20MHz demand, Flp == Fhs/(div*8) <= 20 MHz, here 500000 present 500MHz, so MHz equal 1000
\r
29 so div >= { Fhs/(20Mhz*8) == Fhs/(20000*8) == (Fhs>>4)/10000 }
\r
31 static void mipi_dsih_set_lp_clock(dsih_ctrl_t * instance)
\r
33 uint32_t tx_escape_division = 1;
\r
34 tx_escape_division = (instance->phy_feq>>4);
\r
35 tx_escape_division = (tx_escape_division+9999)/10000;//ceiling calc
\r
36 if (instance->log_info != 0)
\r
38 instance->log_info("sprdfb:[%s]: lp frequence div:%d\n", __FUNCTION__, tx_escape_division);
\r
40 mipi_dsih_hal_tx_escape_division(instance, (uint8_t)tx_escape_division);
\r
43 dsih_error_t mipi_dsih_open(dsih_ctrl_t * instance)
\r
45 dsih_error_t err = OK;
\r
46 uint32_t version = 0;
\r
51 return ERR_DSI_INVALID_INSTANCE;
\r
53 else if ((instance->core_read_function == 0) || (instance->core_write_function == 0))
\r
55 return ERR_DSI_INVALID_IO;
\r
57 else if (instance->status == INITIALIZED)
\r
59 return ERR_DSI_INVALID_INSTANCE;
\r
61 else if (mipi_dsih_dphy_open(&(instance->phy_instance)))
\r
63 return ERR_DSI_PHY_INVALID;
\r
67 instance->status = NOT_INITIALIZED;
\r
68 version = mipi_dsih_hal_get_version(instance);
\r
69 for (i = 0; i < mipi_dsih_no_of_versions; i++)
\r
71 if (version == mipi_dsih_supported_versions[i])
\r
76 /* no matching supported version has been found*/
\r
77 if (i >= mipi_dsih_no_of_versions)
\r
79 if (instance->log_info != 0)
\r
81 instance->log_info("driver does not support this core version 0x%lX", version);
\r
83 return ERR_DSI_CORE_INCOMPATIBLE;
\r
86 //mipi_dsih_hal_power(instance, 0);//Jessica
\r
87 //mipi_dsih_hal_power(instance, 1);//Jessica
\r
88 mipi_dsih_hal_dpi_color_mode_pol(instance, !instance->color_mode_polarity);
\r
89 mipi_dsih_hal_dpi_shut_down_pol(instance, !instance->shut_down_polarity);
\r
90 err = mipi_dsih_phy_hs2lp_config(instance, instance->max_hs_to_lp_cycles);
\r
91 err |= mipi_dsih_phy_lp2hs_config(instance, instance->max_lp_to_hs_cycles);
\r
92 err |= mipi_dsih_phy_bta_time(instance, instance->max_bta_cycles);
\r
95 return ERR_DSI_OVERFLOW;
\r
97 /* by default, return to LP during ALL, unless otherwise specified*/
\r
98 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
99 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
100 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
101 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
102 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
103 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
104 /* by default, all commands are sent in LP */
\r
105 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, 1);
\r
106 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, 1);
\r
107 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, 1); /* long packet*/
\r
108 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, 1);
\r
109 /*Jessica add to support max rd packet size command*/
\r
110 mipi_dsih_hal_max_rd_packet_size_type(instance, 1);
\r
111 mipi_dsih_hal_gen_wr_tx_type(instance, 0, 1);
\r
112 mipi_dsih_hal_gen_wr_tx_type(instance, 1, 1);
\r
113 mipi_dsih_hal_gen_wr_tx_type(instance, 2, 1);
\r
114 mipi_dsih_hal_gen_wr_tx_type(instance, 3, 1); /* long packet*/
\r
115 mipi_dsih_hal_gen_rd_tx_type(instance, 0, 1);
\r
116 mipi_dsih_hal_gen_rd_tx_type(instance, 1, 1);
\r
117 mipi_dsih_hal_gen_rd_tx_type(instance, 2, 1);
\r
118 /* by default, RX_VC = 0, NO EOTp, EOTn, BTA, ECC rx and CRC rx */
\r
119 mipi_dsih_hal_gen_rd_vc(instance, 0);
\r
120 mipi_dsih_hal_gen_eotp_rx_en(instance, 0);
\r
121 mipi_dsih_hal_gen_eotp_tx_en(instance, 0);
\r
122 mipi_dsih_hal_bta_en(instance, 0);
\r
123 mipi_dsih_hal_gen_ecc_rx_en(instance, 0);
\r
124 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
125 mipi_dsih_hal_power(instance, 0);//Jessica
\r
126 mipi_dsih_hal_power(instance, 1);//Jessica
\r
127 /* initialize pll so escape clocks could be generated at 864MHz, 1 lane */
\r
128 /* however the high speed clock will not be requested */
\r
129 //err = mipi_dsih_dphy_configure(&(instance->phy_instance), 1, DEFAULT_BYTE_CLOCK);
\r
131 err = mipi_dsih_dphy_configure(&(instance->phy_instance), instance->max_lanes, 190*1000);
\r
134 return err; /* ERR_DSI_PHY_POWERUP; */
\r
137 /* dividing by 6 is aimed for max PHY frequency, 1GHz */
\r
138 //mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessica
\r
139 mipi_dsih_set_lp_clock(instance);
\r
140 instance->status = INITIALIZED;
\r
143 dsih_error_t mipi_dsih_close(dsih_ctrl_t * instance)
\r
147 return ERR_DSI_INVALID_INSTANCE;
\r
149 if (instance->status != INITIALIZED)
\r
151 return ERR_DSI_INVALID_INSTANCE;
\r
153 mipi_dsih_dphy_close(&(instance->phy_instance));
\r
154 mipi_dsih_hal_power(instance, 0);
\r
157 void mipi_dsih_allow_return_to_lp(dsih_ctrl_t * instance, int hfp, int hbp, int vactive, int vfp, int vbp, int vsync)
\r
164 if (instance->status == INITIALIZED)
\r
166 mipi_dsih_hal_dpi_lp_during_hfp(instance, hfp);
\r
167 mipi_dsih_hal_dpi_lp_during_hbp(instance, hbp);
\r
168 mipi_dsih_hal_dpi_lp_during_vactive(instance, vactive);
\r
169 mipi_dsih_hal_dpi_lp_during_vfp(instance, vfp);
\r
170 mipi_dsih_hal_dpi_lp_during_vbp(instance, vbp);
\r
171 mipi_dsih_hal_dpi_lp_during_vsync(instance, vsync);
\r
175 if (instance->log_error != 0)
\r
177 instance->log_error("invalid instance");
\r
180 void mipi_dsih_dcs_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
187 if (instance->status == INITIALIZED)
\r
189 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, short_write);
\r
190 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, short_write);
\r
191 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
192 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, short_read);
\r
196 if (instance->log_error != 0)
\r
198 instance->log_error("invalid instance");
\r
201 void mipi_dsih_gen_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
208 if (instance->status == INITIALIZED)
\r
210 mipi_dsih_hal_gen_wr_tx_type(instance, 0, short_write);
\r
211 mipi_dsih_hal_gen_wr_tx_type(instance, 1, short_write);
\r
212 mipi_dsih_hal_gen_wr_tx_type(instance, 2, short_write);
\r
213 mipi_dsih_hal_gen_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
214 mipi_dsih_hal_gen_rd_tx_type(instance, 0, short_read);
\r
215 mipi_dsih_hal_gen_rd_tx_type(instance, 1, short_read);
\r
216 mipi_dsih_hal_gen_rd_tx_type(instance, 2, short_read);
\r
220 if (instance->log_error != 0)
\r
222 instance->log_error("invalid instance");
\r
225 /* packet handling */
\r
226 dsih_error_t mipi_dsih_enable_rx(dsih_ctrl_t * instance, int enable)
\r
228 mipi_dsih_hal_bta_en(instance, enable);
\r
231 dsih_error_t mipi_dsih_peripheral_ack(dsih_ctrl_t * instance, int enable)
\r
235 if (instance->status == INITIALIZED)
\r
237 mipi_dsih_hal_cmd_ack_en(instance, enable);
\r
240 mipi_dsih_hal_bta_en(instance, 1);
\r
245 return ERR_DSI_INVALID_INSTANCE;
\r
247 dsih_error_t mipi_dsih_tear_effect_ack(dsih_ctrl_t * instance, int enable)
\r
251 if (instance->status == INITIALIZED)
\r
253 mipi_dsih_hal_tear_effect_ack_en(instance, enable);
\r
256 mipi_dsih_hal_bta_en(instance, 1);
\r
261 return ERR_DSI_INVALID_INSTANCE;
\r
263 dsih_error_t mipi_dsih_eotp_rx(dsih_ctrl_t * instance, int enable)
\r
267 if (instance->status == INITIALIZED)
\r
269 mipi_dsih_hal_gen_eotp_rx_en(instance, enable);
\r
272 mipi_dsih_hal_bta_en(instance, 1);
\r
277 return ERR_DSI_INVALID_INSTANCE;
\r
279 dsih_error_t mipi_dsih_ecc_rx(dsih_ctrl_t * instance, int enable)
\r
283 if (instance->status == INITIALIZED)
\r
285 mipi_dsih_hal_gen_ecc_rx_en(instance, enable);
\r
288 mipi_dsih_hal_bta_en(instance, 1);
\r
293 return ERR_DSI_INVALID_INSTANCE;
\r
295 dsih_error_t mipi_dsih_eotp_tx(dsih_ctrl_t * instance, int enable)
\r
299 if (instance->status == INITIALIZED)
\r
301 mipi_dsih_hal_gen_eotp_tx_en(instance, enable);
\r
305 return ERR_DSI_INVALID_INSTANCE;
\r
307 dsih_error_t mipi_dsih_dpi_video(dsih_ctrl_t * instance, dsih_dpi_video_t * video_params)
\r
309 dsih_error_t err_code = OK;
\r
310 uint16_t bytes_per_pixel_x100 = 0; /* bpp x 100 because it can be 2.25 */
\r
311 uint16_t video_size = 0;
\r
312 uint32_t ratio_clock_xPF = 0; /* holds dpi clock/byte clock times precision factor */
\r
313 uint16_t null_packet_size = 0;
\r
314 uint8_t video_size_step = 1;
\r
315 uint32_t hs_timeout = 0;
\r
316 uint32_t total_bytes = 0;
\r
317 uint32_t bytes_per_chunk = 0;
\r
318 uint32_t no_of_chunks = 0;
\r
319 uint32_t bytes_left = 0;
\r
320 uint32_t chunk_overhead = 0;
\r
322 /* check DSI controller instance */
\r
323 if ((instance == 0) || (video_params == 0))
\r
325 return ERR_DSI_INVALID_INSTANCE;
\r
327 if (instance->status != INITIALIZED)
\r
329 return ERR_DSI_INVALID_INSTANCE;
\r
331 /* set up phy pll to required lane clock */
\r
333 //err_code = mipi_dsih_dphy_configure(&(instance->phy_instance), video_params->no_of_lanes, video_params->byte_clock * 8);
\r
336 // return err_code;
\r
339 ratio_clock_xPF = (video_params->byte_clock * PRECISION_FACTOR) / (video_params->pixel_clock);
\r
340 video_size = video_params->h_active_pixels;
\r
341 /* set up ACKs and error reporting */
\r
342 mipi_dsih_hal_dpi_frame_ack_en(instance, video_params->receive_ack_packets);
\r
343 if (video_params->receive_ack_packets)
\r
344 { /* if ACK is requested, enable BTA, otherwise leave as is */
\r
345 mipi_dsih_hal_bta_en(instance, 1);
\r
347 mipi_dsih_hal_gen_cmd_mode_en(instance, 0);
\r
348 mipi_dsih_hal_dpi_video_mode_en(instance, 1);
\r
349 /* get bytes per pixel and video size step (depending if loosely or not */
\r
350 switch (video_params->color_coding)
\r
352 case COLOR_CODE_16BIT_CONFIG1:
\r
353 case COLOR_CODE_16BIT_CONFIG2:
\r
354 case COLOR_CODE_16BIT_CONFIG3:
\r
355 bytes_per_pixel_x100 = 200;
\r
356 video_size_step = 1;
\r
358 case COLOR_CODE_18BIT_CONFIG1:
\r
359 case COLOR_CODE_18BIT_CONFIG2:
\r
360 mipi_dsih_hal_dpi_18_loosely_packet_en(instance, video_params->is_18_loosely);
\r
361 bytes_per_pixel_x100 = 225;
\r
362 if (!video_params->is_18_loosely)
\r
363 { /* 18bits per pixel and NOT loosely, packets should be multiples of 4 */
\r
364 video_size_step = 4;
\r
365 /* round up active H pixels to a multiple of 4 */
\r
366 for (; (video_size % 4) != 0; video_size++)
\r
373 video_size_step = 1;
\r
376 case COLOR_CODE_24BIT:
\r
377 bytes_per_pixel_x100 = 300;
\r
378 video_size_step = 1;
\r
381 if (instance->log_error != 0)
\r
383 instance->log_error("invalid color coding");
\r
385 err_code = ERR_DSI_COLOR_CODING;
\r
388 if (err_code == OK)
\r
390 err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding);
\r
392 if (err_code != OK)
\r
396 mipi_dsih_hal_dpi_video_mode_type(instance, video_params->video_mode);
\r
397 mipi_dsih_hal_dpi_hline(instance, (uint16_t)(((video_params->h_total_pixels) * ratio_clock_xPF) / PRECISION_FACTOR));
\r
398 mipi_dsih_hal_dpi_hbp(instance, ((video_params->h_back_porch_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
399 mipi_dsih_hal_dpi_hsa(instance, ((video_params->h_sync_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
400 mipi_dsih_hal_dpi_vactive(instance, video_params->v_active_lines);
\r
401 mipi_dsih_hal_dpi_vfp(instance, video_params->v_total_lines - (video_params->v_back_porch_lines + video_params->v_sync_lines + video_params->v_active_lines));
\r
402 mipi_dsih_hal_dpi_vbp(instance, video_params->v_back_porch_lines);
\r
403 mipi_dsih_hal_dpi_vsync(instance, video_params->v_sync_lines);
\r
404 mipi_dsih_hal_dpi_hsync_pol(instance, !video_params->h_polarity);
\r
405 mipi_dsih_hal_dpi_vsync_pol(instance, !video_params->v_polarity);
\r
406 mipi_dsih_hal_dpi_dataen_pol(instance, !video_params->data_en_polarity);
\r
408 hs_timeout = ((video_params->h_total_pixels * video_params->v_active_lines) + (DSIH_PIXEL_TOLERANCE * bytes_per_pixel_x100) / 100);
\r
409 for (counter = 0x80; (counter < hs_timeout) && (counter > 2); counter--)
\r
411 if ((hs_timeout % counter) == 0)
\r
413 mipi_dsih_hal_timeout_clock_division(instance, counter);
\r
414 mipi_dsih_hal_lp_rx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
415 mipi_dsih_hal_hs_tx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
419 /* TX_ESC_CLOCK_DIV must be less than 20000KHz */
\r
420 //mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessica
\r
421 mipi_dsih_set_lp_clock(instance);
\r
422 /* video packetisation */
\r
423 if (video_params->video_mode == VIDEO_BURST_WITH_SYNC_PULSES)
\r
425 mipi_dsih_hal_dpi_null_packet_en(instance, 0);
\r
426 mipi_dsih_hal_dpi_multi_packet_en(instance, 0);
\r
427 err_code = mipi_dsih_hal_dpi_null_packet_size(instance, 0);
\r
428 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, 1);
\r
429 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
430 if (err_code != OK)
\r
434 /* BURST by default, returns to LP during ALL empty periods - energy saving */
\r
435 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
436 #if (defined(CONFIG_SC8830) ||defined(CONFIG_SC9630)) && (defined(CONFIG_LCD_720P) || defined(CONFIG_LCD_HD))//LiWei add CONFIG_LCD_HD
\r
437 mipi_dsih_hal_dpi_lp_during_hbp(instance, 0);
\r
439 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
441 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
442 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
443 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
444 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
447 if (instance->log_info != 0)
\r
449 instance->log_info("burst video");
\r
450 instance->log_info("h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
451 instance->log_info("video_size %ld", video_size);
\r
456 { /* non burst transmission */
\r
457 null_packet_size = 0;
\r
458 /* bytes to be sent - first as one chunk*/
\r
459 bytes_per_chunk = (bytes_per_pixel_x100 * video_params->h_active_pixels) / 100 + VIDEO_PACKET_OVERHEAD;
\r
460 /* bytes being received through the DPI interface per byte clock cycle */
\r
461 total_bytes = (ratio_clock_xPF * video_params->no_of_lanes * (video_params->h_total_pixels - video_params->h_back_porch_pixels - video_params->h_sync_pixels)) / PRECISION_FACTOR;
\r
462 /* check if the in pixels actually fit on the DSI link */
\r
463 if (total_bytes >= bytes_per_chunk)
\r
465 chunk_overhead = total_bytes - bytes_per_chunk;
\r
466 /* overhead higher than 1 -> enable multi packets */
\r
467 if (chunk_overhead > 1)
\r
468 { /* MULTI packets */
\r
469 for (video_size = video_size_step; video_size < video_params->h_active_pixels; video_size += video_size_step)
\r
470 { /* determine no of chunks */
\r
471 if ((((video_params->h_active_pixels * PRECISION_FACTOR) / video_size) % PRECISION_FACTOR) == 0)
\r
473 no_of_chunks = video_params->h_active_pixels / video_size;
\r
474 bytes_per_chunk = (bytes_per_pixel_x100 * video_size) / 100 + VIDEO_PACKET_OVERHEAD;
\r
475 if (total_bytes >= (bytes_per_chunk * no_of_chunks))
\r
477 bytes_left = total_bytes - (bytes_per_chunk * no_of_chunks);
\r
482 /* prevent overflow (unsigned - unsigned) */
\r
483 if (bytes_left > (NULL_PACKET_OVERHEAD * no_of_chunks))
\r
485 null_packet_size = (bytes_left - (NULL_PACKET_OVERHEAD * no_of_chunks)) / no_of_chunks;
\r
486 if (null_packet_size > MAX_NULL_SIZE)
\r
487 { /* avoid register overflow */
\r
488 null_packet_size = MAX_NULL_SIZE;
\r
493 { /* no multi packets */
\r
497 if (instance->log_info != 0)
\r
499 instance->log_info("no multi no null video");
\r
500 instance->log_info("h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
501 instance->log_info("video_size %ld", video_size);
\r
503 /************************/
\r
505 /* video size must be a multiple of 4 when not 18 loosely */
\r
506 for (video_size = video_params->h_active_pixels; (video_size % video_size_step) != 0; video_size++)
\r
514 instance->log_error("resolution cannot be sent to display through current settings");
\r
515 err_code = ERR_DSI_OVERFLOW;
\r
518 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, no_of_chunks);
\r
519 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
520 err_code = err_code? err_code: mipi_dsih_hal_dpi_null_packet_size(instance, null_packet_size);
\r
521 mipi_dsih_hal_dpi_null_packet_en(instance, null_packet_size > 0? 1: 0);
\r
522 mipi_dsih_hal_dpi_multi_packet_en(instance, (no_of_chunks > 1)? 1: 0);
\r
525 if (instance->log_info != 0)
\r
527 instance->log_info("total_bytes %d", total_bytes);
\r
528 instance->log_info("bytes_per_chunk %d", bytes_per_chunk);
\r
529 instance->log_info("bytes left %d", bytes_left);
\r
530 instance->log_info("null packets %d", null_packet_size);
\r
531 instance->log_info("chunks %ld", no_of_chunks);
\r
532 instance->log_info("video_size %ld", video_size);
\r
534 /************************/
\r
536 mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel);
\r
537 mipi_dsih_dphy_no_of_lanes(&(instance->phy_instance), video_params->no_of_lanes);
\r
538 /* enable high speed clock */
\r
539 // mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1);
\r
542 dsih_error_t mipi_dsih_dcs_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
544 uint8_t packet_type = 0;
\r
548 return ERR_DSI_OUT_OF_BOUND;
\r
551 if (param_length > 2)
\r
570 packet_type = 0x05; /* DCS short write no param */
\r
576 packet_type = 0x15; /* DCS short write 1 param */
\r
587 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
590 if (instance->log_error != 0)
\r
592 instance->log_error("invalid DCS command");
\r
594 return ERR_DSI_INVALID_COMMAND;
\r
597 switch(param_length)
\r
600 packet_type = 0x05; /* DCS short write no param */
\r
603 packet_type = 0x15; /* DCS short write 1 param */
\r
606 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
610 return mipi_dsih_gen_wr_packet(instance, vc, packet_type, params, param_length);
\r
612 void mipi_dsih_cmd_mode(dsih_ctrl_t * instance, int en)
\r
619 if (instance->status == INITIALIZED)
\r
621 if ((!mipi_dsih_hal_gen_is_cmd_mode(instance)) && en)
\r
622 { /* disable video mode first */
\r
623 mipi_dsih_hal_dpi_video_mode_en(instance, 0);
\r
624 mipi_dsih_hal_gen_cmd_mode_en(instance, 1);
\r
626 else if ((mipi_dsih_hal_gen_is_cmd_mode(instance)) && !en)
\r
628 mipi_dsih_hal_gen_cmd_mode_en(instance, 0);
\r
633 if (instance->log_error != 0)
\r
635 instance->log_error("invalid instance");
\r
638 void mipi_dsih_video_mode(dsih_ctrl_t * instance, int en)
\r
645 if (instance->status == INITIALIZED)
\r
647 if ((!mipi_dsih_hal_dpi_is_video_mode(instance)) && en)
\r
648 { /* disable cmd mode first */
\r
649 mipi_dsih_hal_gen_cmd_mode_en(instance, 0);
\r
650 mipi_dsih_hal_dpi_video_mode_en(instance, 1);
\r
652 else if ((!mipi_dsih_hal_dpi_is_video_mode(instance)) && !en)
\r
654 mipi_dsih_hal_dpi_video_mode_en(instance, 0);
\r
659 if (instance->log_error != 0)
\r
661 instance->log_error("invalid instance");
\r
664 int mipi_dsih_active_mode(dsih_ctrl_t * instance)
\r
666 if (mipi_dsih_hal_gen_is_cmd_mode(instance))
\r
670 else if (mipi_dsih_hal_dpi_is_video_mode(instance))
\r
676 dsih_error_t mipi_dsih_gen_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
678 uint8_t data_type = 0;
\r
679 switch(param_length)
\r
694 return mipi_dsih_gen_wr_packet(instance, vc, data_type, params, param_length);
\r
696 dsih_error_t mipi_dsih_gen_wr_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t* params, uint16_t param_length)
\r
698 dsih_error_t err_code = OK;
\r
699 /* active delay iterator */
\r
704 /* holds padding bytes needed */
\r
705 int compliment_counter = 0;
\r
706 uint8_t* payload = 0;
\r
707 /* temporary variable to arrange bytes into words */
\r
709 uint16_t word_count = 0;
\r
712 return ERR_DSI_INVALID_INSTANCE;
\r
714 if (instance->status != INITIALIZED)
\r
716 return ERR_DSI_INVALID_INSTANCE;
\r
718 if ((params == 0) && (param_length != 0)) /* pointer NULL */
\r
720 return ERR_DSI_OUT_OF_BOUND;
\r
722 if (param_length > 2)
\r
723 { /* long packet - write word count to header, and the rest to payload */
\r
724 payload = params + (2 * sizeof(params[0]));
\r
725 word_count = (params[1] << 8) | params[0];
\r
726 if ((param_length - 2) < word_count)
\r
728 if (instance->log_error != 0)
\r
730 instance->log_error("sent > input payload. complemented with zeroes");
\r
732 compliment_counter = (param_length - 2) - word_count;
\r
734 else if ((param_length - 2) > word_count)
\r
736 if (instance->log_error != 0)
\r
738 instance->log_error("Overflow - input > sent. payload truncated");
\r
741 for (i = 0; i < (param_length - 2); i += j)
\r
744 for (j = 0; (j < 4) && ((j + i) < (param_length - 2)); j++)
\r
745 { /* temp = (payload[i + 3] << 24) | (payload[i + 2] << 16) | (payload[i + 1] << 8) | payload[i]; */
\r
746 temp |= payload[i + j] << (j * 8);
\r
748 /* check if payload Tx fifo is not full */
\r
749 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
751 if (!mipi_dsih_hal_gen_packet_payload(instance, temp))
\r
756 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
758 return ERR_DSI_TIMEOUT;
\r
761 /* if word count entered by the user more than actual parameters received
\r
762 * fill with zeroes - a fail safe mechanism, otherwise controller will
\r
763 * want to send data from an empty buffer */
\r
764 for (i = 0; i < compliment_counter; i++)
\r
766 /* check if payload Tx fifo is not full */
\r
767 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
769 if (!mipi_dsih_hal_gen_packet_payload(instance, 0x00))
\r
774 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
776 return ERR_DSI_TIMEOUT;
\r
780 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
782 /* check if payload Tx fifo is not full */
\r
783 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
785 if (param_length == 0)
\r
787 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, 0x0);
\r
789 else if (param_length == 1)
\r
791 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, params[0]);
\r
795 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, params[1], params[0]);
\r
800 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
802 err_code = ERR_DSI_TIMEOUT;
\r
806 uint16_t mipi_dsih_dcs_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t command, uint8_t bytes_to_read, uint8_t* read_buffer)
\r
812 if (instance->status != INITIALIZED)
\r
832 /* COMMAND_TYPE 0x06 - DCS Read no params refer to DSI spec p.47 */
\r
833 return mipi_dsih_gen_rd_packet(instance, vc, 0x06, 0x0, command, bytes_to_read, read_buffer);
\r
835 if (instance->log_error != 0)
\r
837 instance->log_error("invalid DCS command");
\r
843 uint16_t mipi_dsih_gen_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length, uint8_t bytes_to_read, uint8_t* read_buffer)
\r
845 uint8_t data_type = 0;
\r
850 if (instance->status != INITIALIZED)
\r
854 switch(param_length)
\r
858 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, 0x00, bytes_to_read, read_buffer);
\r
861 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, params[0], bytes_to_read, read_buffer);
\r
864 return mipi_dsih_gen_rd_packet(instance, vc, data_type, params[1], params[0], bytes_to_read, read_buffer);
\r
869 uint16_t mipi_dsih_gen_rd_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t msb_byte, uint8_t lsb_byte, uint8_t bytes_to_read, uint8_t* read_buffer)
\r
871 dsih_error_t err_code = OK;
\r
875 int last_count = 0;
\r
876 uint32_t temp[1] = {0};
\r
881 if (instance->status != INITIALIZED)
\r
885 if (bytes_to_read < 1)
\r
889 if (read_buffer == 0)
\r
893 /* make sure command mode is on */
\r
894 mipi_dsih_cmd_mode(instance, 1);
\r
895 /* make sure receiving is enabled */
\r
896 mipi_dsih_hal_bta_en(instance, 1);
\r
897 /* listen to the same virtual channel as the one sent to */
\r
898 mipi_dsih_hal_gen_rd_vc(instance, vc);
\r
899 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
900 { /* check if payload Tx fifo is not full */
\r
901 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
903 mipi_dsih_hal_gen_packet_header(instance, vc, data_type, msb_byte, lsb_byte);
\r
907 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
909 if (instance->log_error != 0)
\r
911 instance->log_error("tx rd command timed out");
\r
915 /* loop for the number of words to be read */
\r
916 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
917 { /* check if command transaction is done */
\r
918 if (!mipi_dsih_hal_gen_rd_cmd_busy(instance))
\r
920 if (!mipi_dsih_hal_gen_read_fifo_empty(instance))
\r
922 for (counter = 0; (!mipi_dsih_hal_gen_read_fifo_empty(instance)); counter += 4)
\r
924 err_code = mipi_dsih_hal_gen_read_payload(instance, temp);
\r
929 if (counter < bytes_to_read)
\r
931 for (i = 0; i < 4; i++)
\r
933 if ((counter + i) < bytes_to_read)
\r
935 /* put 32 bit temp in 4 bytes of buffer passed by user*/
\r
936 read_buffer[counter + i] = (uint8_t)(temp[0] >> (i * 8));
\r
937 last_count = i + counter;
\r
941 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
943 last_count = i + counter;
\r
950 last_count = counter;
\r
951 for (i = 0; i < 4; i++)
\r
953 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
955 last_count = i + counter;
\r
960 return last_count + 1;
\r
964 if (instance->log_error != 0)
\r
966 instance->log_error("rx buffer empty");
\r
972 if (instance->log_error != 0)
\r
974 instance->log_error("rx command timed out");
\r
978 uint32_t mipi_dsih_dump_register_configuration(dsih_ctrl_t * instance, int all, register_config_t *config, uint16_t config_length)
\r
980 uint32_t current = 0;
\r
981 uint16_t count = 0;
\r
984 return ERR_DSI_INVALID_INSTANCE;
\r
986 if (instance->status != INITIALIZED)
\r
988 return ERR_DSI_INVALID_INSTANCE;
\r
991 { /* dump all registers */
\r
992 for (current = R_DSI_HOST_VERSION; current <= R_DSI_HOST_ERROR_MSK1; count++, current += (R_DSI_HOST_PWR_UP - R_DSI_HOST_VERSION))
\r
994 if ((config_length == 0) || (config == 0) || count >= config_length)
\r
995 { /* no place to write - write to STD IO */
\r
996 if (instance->log_info != 0)
\r
998 instance->log_info("DSI 0x%lX:0x%lX", current, mipi_dsih_read_word(instance, current));
\r
1003 config[count].addr = current;
\r
1004 config[count].data = mipi_dsih_read_word(instance, current);
\r
1012 if (instance->log_error != 0)
\r
1014 instance->log_error("invalid buffer");
\r
1019 for (count = 0; count < config_length; count++)
\r
1021 config[count].data = mipi_dsih_read_word(instance, config[count].addr);
\r
1027 uint32_t mipi_dsih_write_register_configuration(dsih_ctrl_t * instance, register_config_t *config, uint16_t config_length)
\r
1029 uint16_t count = 0;
\r
1030 if (instance == 0)
\r
1032 return ERR_DSI_INVALID_INSTANCE;
\r
1034 if (instance->status != INITIALIZED)
\r
1036 return ERR_DSI_INVALID_INSTANCE;
\r
1038 for (count = 0; count < config_length; count++)
\r
1040 mipi_dsih_write_word(instance, config[count].addr, config[count].data);
\r
1044 dsih_error_t mipi_dsih_register_event(dsih_ctrl_t * instance, dsih_event_t event, void (*handler)(dsih_ctrl_t *, void *))
\r
1046 uint32_t mask = 1;
\r
1047 uint32_t temp = 0;
\r
1048 if (event >= DSI_MAX_EVENT)
\r
1050 return ERR_DSI_INVALID_EVENT;
\r
1054 return ERR_DSI_INVALID_HANDLE;
\r
1056 if (instance == 0)
\r
1058 return ERR_DSI_INVALID_INSTANCE;
\r
1060 if (instance->status != INITIALIZED)
\r
1062 return ERR_DSI_INVALID_INSTANCE;
\r
1064 instance->event_registry[event] = handler;
\r
1065 if (event < HS_CONTENTION)
\r
1067 temp = mipi_dsih_hal_get_error_mask_0(instance, 0xffffffff);
\r
1068 temp &= ~(mask << event);
\r
1069 temp |= (0 & mask) << event;
\r
1070 mipi_dsih_hal_error_mask_0(instance, temp);
\r
1074 temp = mipi_dsih_hal_get_error_mask_1(instance, 0xffffffff);
\r
1075 temp &= ~(mask << (event - HS_CONTENTION));
\r
1076 temp |= (0 & mask) << (event - HS_CONTENTION);
\r
1077 mipi_dsih_hal_error_mask_1(instance, temp);
\r
1078 if (event == RX_CRC_ERR)
\r
1079 { /* automatically enable CRC reporting */
\r
1080 mipi_dsih_hal_gen_crc_rx_en(instance, 1);
\r
1085 dsih_error_t mipi_dsih_unregister_event(dsih_ctrl_t * instance, dsih_event_t event)
\r
1087 uint32_t mask = 1;
\r
1088 uint32_t temp = 0;
\r
1089 if (event >= DSI_MAX_EVENT)
\r
1091 return ERR_DSI_INVALID_EVENT;
\r
1093 if (instance == 0)
\r
1095 return ERR_DSI_INVALID_INSTANCE;
\r
1097 if (instance->status != INITIALIZED)
\r
1099 return ERR_DSI_INVALID_INSTANCE;
\r
1101 instance->event_registry[event] = 0;
\r
1102 if (event < HS_CONTENTION)
\r
1104 temp = mipi_dsih_hal_get_error_mask_0(instance, 0xffffffff);
\r
1105 temp &= ~(mask << event);
\r
1106 temp |= (1 & mask) << event;
\r
1107 mipi_dsih_hal_error_mask_0(instance, temp);
\r
1111 temp = mipi_dsih_hal_get_error_mask_1(instance, 0xffffffff);
\r
1112 temp &= ~(mask << (event - HS_CONTENTION));
\r
1113 temp |= (1 & mask) << (event - HS_CONTENTION);
\r
1114 mipi_dsih_hal_error_mask_1(instance, temp);
\r
1115 if (event == RX_CRC_ERR)
\r
1116 { /* automatically disable CRC reporting */
\r
1117 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1122 dsih_error_t mipi_dsih_unregister_all_events(dsih_ctrl_t * instance)
\r
1125 if (instance == 0)
\r
1127 return ERR_DSI_INVALID_INSTANCE;
\r
1129 if (instance->status != INITIALIZED)
\r
1131 return ERR_DSI_INVALID_INSTANCE;
\r
1133 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1135 instance->event_registry[i] = 0;
\r
1137 mipi_dsih_hal_error_mask_0(instance, 0xffffff);
\r
1138 mipi_dsih_hal_error_mask_1(instance, 0xffffff);
\r
1139 /* automatically disable CRC reporting */
\r
1140 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1143 void mipi_dsih_event_handler(void * param)
\r
1145 dsih_ctrl_t * instance = (dsih_ctrl_t *)(param);
\r
1147 uint32_t status_0;
\r
1148 uint32_t status_1;
\r
1149 if (instance == 0)
\r
1154 status_0 = mipi_dsih_hal_error_status_0(instance, 0xffffffff);
\r
1155 status_1 = mipi_dsih_hal_error_status_1(instance, 0xffffffff);
\r
1157 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1159 if (instance->event_registry[i] != 0)
\r
1161 if (i < HS_CONTENTION)
\r
1163 if ((status_0 & (1 << i)) != 0)
\r
1165 instance->event_registry[i](instance, &i);
\r
1170 if ((status_1 & (1 << (i - HS_CONTENTION))) != 0)
\r
1172 instance->event_registry[i](instance, &i);
\r
1178 void mipi_dsih_reset_controller(dsih_ctrl_t * instance)
\r
1180 mipi_dsih_hal_power(instance, 0);
\r
1181 mipi_dsih_hal_power(instance, 1);
\r
1183 void mipi_dsih_shutdown_controller(dsih_ctrl_t * instance, int shutdown)
\r
1185 mipi_dsih_hal_power(instance, !shutdown);
\r
1187 void mipi_dsih_reset_phy(dsih_ctrl_t * instance)
\r
1189 mipi_dsih_dphy_reset(&(instance->phy_instance), 0);
\r
1190 mipi_dsih_dphy_reset(&(instance->phy_instance), 1);
\r
1192 void mipi_dsih_shutdown_phy(dsih_ctrl_t * instance, int shutdown)
\r
1194 mipi_dsih_dphy_shutdown(&(instance->phy_instance), !shutdown);
\r