2 * @file mipi_dsih_api.c
\r
3 * @brief DWC MIPI DSI Host driver
\r
9 #include "mipi_dsih_api.h"
\r
10 #include "mipi_dsih_hal.h"
\r
11 #include "mipi_dsih_dphy.h"
\r
12 /* whether to get debug messages (1) or not (0) */
\r
15 #define PRECISION_FACTOR 1000
\r
16 #define VIDEO_PACKET_OVERHEAD 6
\r
17 #define NULL_PACKET_OVERHEAD 6
\r
18 #define SHORT_PACKET 4
\r
19 #define BLANKING_PACKET 6
\r
20 /** Version supported by this driver */
\r
21 static const uint32_t mipi_dsih_supported_versions[] = {0x3132302A, 0x3132312A};
\r
22 static const uint32_t mipi_dsih_no_of_versions = sizeof(mipi_dsih_supported_versions) / sizeof(uint32_t);
\r
25 func:mipi_dsih_set_lp_clock
\r
26 desc:in low-power mode, max PHY frequency should smaller than 20MHz,
\r
27 in synopsys IP, low-power clock divide from high-speed clock,
\r
28 this function is designed to adapt low-power clock to various high-speed clock.
\r
30 Fhs : high-speed frequence
\r
31 Flp : low-power frequence
\r
32 div : mipi_dsih_hal_tx_escape_division() param, byte clock unit.
\r
33 because of the 20MHz demand, Flp == Fhs/(div*8) <= 20 MHz, here 500000 present 500MHz, so MHz equal 1000
\r
34 so div >= { Fhs/(20Mhz*8) == Fhs/(20000*8) == (Fhs>>4)/10000 }
\r
36 static void mipi_dsih_set_lp_clock(dsih_ctrl_t * instance)
\r
38 uint32_t tx_escape_division = 1;
\r
39 tx_escape_division = (instance->phy_feq>>4);
\r
40 tx_escape_division = (tx_escape_division+9999)/10000;//ceiling calc
\r
41 if (instance->log_info != 0)
\r
43 instance->log_info("sprdfb:[%s]: lp frequence div:%d\n", __FUNCTION__, tx_escape_division);
\r
45 mipi_dsih_hal_tx_escape_division(instance, (uint8_t)tx_escape_division);
\r
49 * Open controller instance
\r
50 * - Check if driver is compatible with core version
\r
51 * - Check if instance context data structure is not NULL
\r
52 * - Bring up PHY for any transmissions in low power
\r
53 * + Includes programming PLL to DEFAULT_BYTE_CLOCK
\r
54 * - Bring up controller and perform initial configuration
\r
55 * + Includes start all commands transmision in LP
\r
56 * + Controller will not turn the bus around after commands
\r
57 * + program counters
\r
58 * @param instance pointer to structure holding the DSI Host core information
\r
59 * @return dsih_error_t
\r
60 * @note this function must be called before any other function in this API
\r
62 dsih_error_t mipi_dsih_open(dsih_ctrl_t * instance)
\r
64 dsih_error_t err = OK;
\r
65 uint32_t version = 0;
\r
70 return ERR_DSI_INVALID_INSTANCE;
\r
72 else if ((instance->core_read_function == 0) || (instance->core_write_function == 0))
\r
74 return ERR_DSI_INVALID_IO;
\r
76 else if (instance->status == INITIALIZED)
\r
78 return ERR_DSI_INVALID_INSTANCE;
\r
80 else if (mipi_dsih_dphy_open(&(instance->phy_instance)))
\r
82 return ERR_DSI_PHY_INVALID;
\r
86 instance->status = NOT_INITIALIZED;
\r
87 version = mipi_dsih_hal_get_version(instance);
\r
88 for (i = 0; i < mipi_dsih_no_of_versions; i++)
\r
90 if (version == mipi_dsih_supported_versions[i])
\r
95 /* no matching supported version has been found*/
\r
96 if (i >= mipi_dsih_no_of_versions)
\r
98 if (instance->log_info != 0)
\r
100 instance->log_info("driver does not support this core version 0x%lX", version);
\r
102 return ERR_DSI_CORE_INCOMPATIBLE;
\r
106 mipi_dsih_hal_power(instance, 0);//tianci 1.21a modify
\r
107 //mipi_dsih_hal_power(instance, 0);//Jessica masked
\r
108 //mipi_dsih_hal_power(instance, 1);//Jessica masked
\r
109 mipi_dsih_hal_dpi_color_mode_pol(instance, !instance->color_mode_polarity);
\r
110 mipi_dsih_hal_dpi_shut_down_pol(instance, !instance->shut_down_polarity);
\r
112 //err = mipi_dsih_phy_hs2lp_config(instance, instance->max_hs_to_lp_cycles);//tianci 1.21a modify
\r
113 //err |= mipi_dsih_phy_lp2hs_config(instance, instance->max_lp_to_hs_cycles);//tianci 1.21a modify
\r
115 mipi_dsih_hal_int_mask_0(instance, 0xffffff);//tianci 1.21a modify
\r
116 mipi_dsih_hal_int_mask_1(instance, 0xffffff);//tianci 1.21a modify
\r
117 err = mipi_dsih_phy_bta_time(instance, instance->max_bta_cycles);
\r
120 return ERR_DSI_OVERFLOW;
\r
122 /* by default, return to LP during ALL, unless otherwise specified*/
\r
123 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
124 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
125 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
126 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
127 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
128 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
129 /* by default, all commands are sent in LP */
\r
130 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, 1);
\r
131 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, 1);
\r
132 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, 1); /* long packet*/
\r
133 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, 1);
\r
134 /*Jessica add to support max rd packet size command*/
\r
135 mipi_dsih_hal_max_rd_packet_size_type(instance, 1);
\r
136 mipi_dsih_hal_gen_wr_tx_type(instance, 0, 1);
\r
137 mipi_dsih_hal_gen_wr_tx_type(instance, 1, 1);
\r
138 mipi_dsih_hal_gen_wr_tx_type(instance, 2, 1);
\r
139 mipi_dsih_hal_gen_wr_tx_type(instance, 3, 1); /* long packet*/
\r
140 mipi_dsih_hal_gen_rd_tx_type(instance, 0, 1);
\r
141 mipi_dsih_hal_gen_rd_tx_type(instance, 1, 1);
\r
142 mipi_dsih_hal_gen_rd_tx_type(instance, 2, 1);
\r
143 /* by default, RX_VC = 0, NO EOTp, EOTn, BTA, ECC rx and CRC rx */
\r
144 mipi_dsih_hal_gen_rd_vc(instance, 0);
\r
145 mipi_dsih_hal_gen_eotp_rx_en(instance, 0);
\r
146 mipi_dsih_hal_gen_eotp_tx_en(instance, 0);
\r
147 mipi_dsih_hal_bta_en(instance, 0);
\r
148 mipi_dsih_hal_gen_ecc_rx_en(instance, 0);
\r
149 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
150 //mipi_dsih_hal_power(instance, 0);//tianci 1.21a modify
\r
151 mipi_dsih_hal_power(instance, 1);
\r
153 /* dividing by 6 is aimed for max PHY frequency, 1GHz */
\r
154 // mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessica
\r
155 mipi_dsih_set_lp_clock(instance);
\r
157 instance->status = INITIALIZED;
\r
159 /* initialize pll so escape clocks could be generated at 864MHz, 1 lane */
\r
160 /* however the high speed clock will not be requested */
\r
162 //err = mipi_dsih_dphy_configure(&(instance->phy_instance), 1, DEFAULT_BYTE_CLOCK);
\r
166 * Close DSI Host driver
\r
167 * - Free up resources and shutdown host controller and PHY
\r
168 * @param instance pointer to structure holding the DSI Host core information
\r
169 * @return dsih_error_t
\r
171 dsih_error_t mipi_dsih_close(dsih_ctrl_t * instance)
\r
175 return ERR_DSI_INVALID_INSTANCE;
\r
177 if (instance->status != INITIALIZED)
\r
179 return ERR_DSI_INVALID_INSTANCE;
\r
181 mipi_dsih_hal_int_mask_0(instance, 0xffffff);
\r
182 mipi_dsih_hal_int_mask_1(instance, 0xffffff);
\r
183 mipi_dsih_dphy_close(&(instance->phy_instance));
\r
184 mipi_dsih_hal_power(instance, 0);
\r
185 instance->status = NOT_INITIALIZED;
\r
189 * Enable return to low power mode inside video periods when timing allows
\r
190 * @param instance pointer to structure holding the DSI Host core information
\r
191 * @param hfp allow to return to lp inside horizontal front porch pixels
\r
192 * @param hbp allow to return to lp inside horizontal back porch pixels
\r
193 * @param vactive allow to return to lp inside vertical active lines
\r
194 * @param vfp allow to return to lp inside vertical front porch lines
\r
195 * @param vbp allow to return to lp inside vertical back porch lines
\r
196 * @param vsync allow to return to lp inside vertical sync lines
\r
198 void mipi_dsih_allow_return_to_lp(dsih_ctrl_t * instance, int hfp, int hbp, int vactive, int vfp, int vbp, int vsync)
\r
200 if(0 == instance)//jessica
\r
205 if (instance->status == INITIALIZED)
\r
207 mipi_dsih_hal_dpi_lp_during_hfp(instance, hfp);
\r
208 mipi_dsih_hal_dpi_lp_during_hbp(instance, hbp);
\r
209 mipi_dsih_hal_dpi_lp_during_vactive(instance, vactive);
\r
210 mipi_dsih_hal_dpi_lp_during_vfp(instance, vfp);
\r
211 mipi_dsih_hal_dpi_lp_during_vbp(instance, vbp);
\r
212 mipi_dsih_hal_dpi_lp_during_vsync(instance, vsync);
\r
215 if (instance->log_error != 0)
\r
217 instance->log_error("invalid instance");
\r
222 * Set DCS command packet transmission to low power
\r
223 * @param instance pointer to structure holding the DSI Host core information
\r
224 * @param long_write command packets
\r
225 * @param short_write command packets with none and one parameters
\r
226 * @param short_read command packets with none parameters
\r
228 void mipi_dsih_dcs_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
235 if (instance->status == INITIALIZED)
\r
237 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, short_write);
\r
238 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, short_write);
\r
239 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
240 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, short_read);
\r
243 if (instance->log_error != 0)
\r
245 instance->log_error("invalid instance");
\r
249 * Set Generic interface packet transmission to low power
\r
250 * @param instance pointer to structure holding the DSI Host core information
\r
251 * @param long_write command packets
\r
252 * @param short_write command packets with none, one and two parameters
\r
253 * @param short_read command packets with none, one and two parameters
\r
255 void mipi_dsih_gen_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
262 if (instance->status == INITIALIZED)
\r
264 mipi_dsih_hal_gen_wr_tx_type(instance, 0, short_write);
\r
265 mipi_dsih_hal_gen_wr_tx_type(instance, 1, short_write);
\r
266 mipi_dsih_hal_gen_wr_tx_type(instance, 2, short_write);
\r
267 mipi_dsih_hal_gen_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
268 mipi_dsih_hal_gen_rd_tx_type(instance, 0, short_read);
\r
269 mipi_dsih_hal_gen_rd_tx_type(instance, 1, short_read);
\r
270 mipi_dsih_hal_gen_rd_tx_type(instance, 2, short_read);
\r
273 if (instance->log_error != 0)
\r
275 instance->log_error("invalid instance");
\r
278 /* packet handling */
\r
280 * Enable all receiving activities (applying a Bus Turn Around).
\r
281 * - Disabling using this function will stop all acknowledges by the
\r
282 * peripherals and no interrupts from low-level protocol error reporting
\r
283 * will be able to rise.
\r
284 * - Enabling any receiving function (command or frame ACKs, ECC,
\r
285 * tear effect ACK or EoTp receiving) will enable this automatically,
\r
286 * but it must be EXPLICITLY be disabled to disabled all kinds of
\r
287 * receiving functionality.
\r
288 * @param instance pointer to structure holding the DSI Host core information
\r
289 * @param enable or disable
\r
290 * @return error code
\r
292 dsih_error_t mipi_dsih_enable_rx(dsih_ctrl_t * instance, int enable)
\r
294 mipi_dsih_hal_bta_en(instance, enable);
\r
298 * Enable command packet acknowledges by the peripherals
\r
299 * - For interrupts to rise the monitored event must be registered
\r
300 * using the event_register function
\r
301 * @param instance pointer to structure holding the DSI Host core information
\r
302 * @param enable or disable
\r
303 * @return error code
\r
305 dsih_error_t mipi_dsih_peripheral_ack(dsih_ctrl_t * instance, int enable)
\r
309 if (instance->status == INITIALIZED)
\r
311 mipi_dsih_hal_cmd_ack_en(instance, enable);
\r
314 mipi_dsih_hal_bta_en(instance, 1);
\r
319 return ERR_DSI_INVALID_INSTANCE;
\r
322 * Enable tearing effect acknowledges by the peripherals (wait for TE)
\r
323 * - It enables the following from the DSI specification
\r
324 * "Since the timing of a TE event is, by definition, unknown to the host
\r
325 * processor, the host processor shall give bus possession to the display
\r
326 * module and then wait for up to one video frame period for the TE response.
\r
327 * During this time, the host processor cannot send new commands, or requests
\r
328 * to the display module, because it does not have bus possession."
\r
329 * @param instance pointer to structure holding the DSI Host core information
\r
330 * @param enable or disable
\r
331 * @return error code
\r
333 dsih_error_t mipi_dsih_tear_effect_ack(dsih_ctrl_t * instance, int enable)
\r
337 if (instance->status == INITIALIZED)
\r
339 mipi_dsih_hal_tear_effect_ack_en(instance, enable);
\r
342 mipi_dsih_hal_bta_en(instance, 1);
\r
347 return ERR_DSI_INVALID_INSTANCE;
\r
350 * Enable the receiving of EoT packets at the end of LS transmission.
\r
351 * @param instance pointer to structure holding the DSI Host core information
\r
352 * @param enable or disable
\r
353 * @return error code
\r
355 dsih_error_t mipi_dsih_eotp_rx(dsih_ctrl_t * instance, int enable)
\r
359 if (instance->status == INITIALIZED)
\r
361 mipi_dsih_hal_gen_eotp_rx_en(instance, enable);
\r
364 mipi_dsih_hal_bta_en(instance, 1);
\r
369 return ERR_DSI_INVALID_INSTANCE;
\r
372 * Enable the listening to ECC bytes. This allows for recovering from
\r
373 * 1 bit errors. To report ECC events, the ECC events should be registered
\r
374 * @param instance pointer to structure holding the DSI Host core information
\r
375 * @param enable or disable
\r
376 * @return error code
\r
378 dsih_error_t mipi_dsih_ecc_rx(dsih_ctrl_t * instance, int enable)
\r
382 if (instance->status == INITIALIZED)
\r
384 mipi_dsih_hal_gen_ecc_rx_en(instance, enable);
\r
387 mipi_dsih_hal_bta_en(instance, 1);
\r
392 return ERR_DSI_INVALID_INSTANCE;
\r
395 * Enable the sending of EoT (End of Transmission) packets at the end of HS
\r
396 * transmission. It was made optional in the DSI spec. for retro-compatibility.
\r
397 * @param instance pointer to structure holding the DSI Host core information
\r
398 * @param enable or disable
\r
399 * @return error code
\r
401 dsih_error_t mipi_dsih_eotp_tx(dsih_ctrl_t * instance, int enable)
\r
405 if (instance->status == INITIALIZED)
\r
407 mipi_dsih_hal_gen_eotp_tx_en(instance, enable);
\r
411 return ERR_DSI_INVALID_INSTANCE;
\r
414 * Configure DPI video interface
\r
415 * - If not in burst mode, it will compute the video and null packet sizes
\r
416 * according to necessity
\r
417 * - Configure timers for data lanes and/or clock lane to return to LP when
\r
418 * bandwidth is not filled by data
\r
419 * @param instance pointer to structure holding the DSI Host core information
\r
420 * @param video_params pointer to video stream-to-send information
\r
421 * @return error code
\r
423 dsih_error_t mipi_dsih_dpi_video(dsih_ctrl_t * instance, dsih_dpi_video_t * video_params)
\r
425 dsih_error_t err_code = OK;
\r
426 uint16_t bytes_per_pixel_x100 = 0; /* bpp x 100 because it can be 2.25 */
\r
427 uint16_t video_size = 0;
\r
428 uint32_t ratio_clock_xPF = 0; /* holds dpi clock/byte clock times precision factor */
\r
429 uint16_t null_packet_size = 0;
\r
430 uint8_t video_size_step = 1;
\r
431 uint32_t hs_timeout = 0;
\r
432 uint32_t total_bytes = 0;
\r
433 uint32_t bytes_per_chunk = 0;
\r
434 uint32_t no_of_chunks = 0;
\r
435 uint32_t bytes_left = 0;
\r
436 uint32_t chunk_overhead = 0;
\r
438 /* check DSI controller instance */
\r
439 if ((instance == 0) || (video_params == 0))
\r
441 return ERR_DSI_INVALID_INSTANCE;
\r
443 if (instance->status != INITIALIZED)
\r
445 return ERR_DSI_INVALID_INSTANCE;
\r
447 if (video_params->no_of_lanes > instance->max_lanes)
\r
449 return ERR_DSI_OUT_OF_BOUND;
\r
451 /* set up phy pll to required lane clock */
\r
452 err_code = mipi_dsih_phy_hs2lp_config(instance, video_params->max_hs_to_lp_cycles);
\r
453 err_code |= mipi_dsih_phy_lp2hs_config(instance, video_params->max_lp_to_hs_cycles);
\r
454 err_code = mipi_dsih_phy_clk_hs2lp_config(instance, video_params->max_clk_hs_to_lp_cycles);
\r
455 err_code |= mipi_dsih_phy_clk_lp2hs_config(instance, video_params->max_clk_lp_to_hs_cycles);
\r
456 mipi_dsih_non_continuous_clock(instance,video_params->non_continuous_clock);
\r
458 //err_code = mipi_dsih_dphy_configure(&(instance->phy_instance), video_params->no_of_lanes, video_params->byte_clock * 8);
\r
461 // return err_code;
\r
464 ratio_clock_xPF = (video_params->byte_clock * PRECISION_FACTOR) / (video_params->pixel_clock);
\r
465 video_size = video_params->h_active_pixels;
\r
466 /* set up ACKs and error reporting */
\r
467 mipi_dsih_hal_dpi_frame_ack_en(instance, video_params->receive_ack_packets);
\r
468 if (video_params->receive_ack_packets)
\r
470 /* if ACK is requested, enable BTA, otherwise leave as is */
\r
471 mipi_dsih_hal_bta_en(instance, 1);
\r
473 /* mipi_dsih_hal_gen_cmd_mode_en(instance, 0); */
\r
474 mipi_dsih_hal_dpi_video_mode_en(instance, 1);
\r
475 /* get bytes per pixel and video size step (depending if loosely or not */
\r
476 switch (video_params->color_coding)
\r
478 case COLOR_CODE_16BIT_CONFIG1:
\r
479 case COLOR_CODE_16BIT_CONFIG2:
\r
480 case COLOR_CODE_16BIT_CONFIG3:
\r
481 bytes_per_pixel_x100 = 200;
\r
482 video_size_step = 1;
\r
484 case COLOR_CODE_18BIT_CONFIG1:
\r
485 case COLOR_CODE_18BIT_CONFIG2:
\r
486 mipi_dsih_hal_dpi_18_loosely_packet_en(instance, video_params->is_18_loosely);
\r
487 bytes_per_pixel_x100 = 225;
\r
488 if (!video_params->is_18_loosely)
\r
490 /* 18bits per pixel and NOT loosely, packets should be multiples of 4 */
\r
491 video_size_step = 4;
\r
492 /* round up active H pixels to a multiple of 4 */
\r
493 for (; (video_size % 4) != 0; video_size++)
\r
500 video_size_step = 1;
\r
503 case COLOR_CODE_24BIT:
\r
504 bytes_per_pixel_x100 = 300;
\r
505 video_size_step = 1;
\r
507 case COLOR_CODE_20BIT_YCC422_LOOSELY:
\r
508 bytes_per_pixel_x100 = 250;
\r
509 video_size_step = 2;
\r
510 /* round up active H pixels to a multiple of 2 */
\r
511 if ((video_size % 2) != 0)
\r
516 case COLOR_CODE_24BIT_YCC422:
\r
517 bytes_per_pixel_x100 = 300;
\r
518 video_size_step = 2;
\r
519 /* round up active H pixels to a multiple of 2 */
\r
520 if ((video_size % 2) != 0)
\r
525 case COLOR_CODE_16BIT_YCC422:
\r
526 bytes_per_pixel_x100 = 200;
\r
527 video_size_step = 2;
\r
528 /* round up active H pixels to a multiple of 2 */
\r
529 if ((video_size % 2) != 0)
\r
534 case COLOR_CODE_30BIT:
\r
535 bytes_per_pixel_x100 = 375;
\r
536 video_size_step = 2;
\r
538 case COLOR_CODE_36BIT:
\r
539 bytes_per_pixel_x100 = 450;
\r
540 video_size_step = 2;
\r
542 case COLOR_CODE_12BIT_YCC420:
\r
543 bytes_per_pixel_x100 = 150;
\r
544 video_size_step = 2;
\r
545 /* round up active H pixels to a multiple of 2 */
\r
546 if ((video_size % 2) != 0)
\r
552 if (instance->log_error != 0)
\r
554 instance->log_error("invalid color coding");
\r
556 err_code = ERR_DSI_COLOR_CODING;
\r
559 if (err_code == OK)
\r
561 err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding);
\r
563 if (err_code != OK)
\r
567 mipi_dsih_hal_dpi_video_mode_type(instance, video_params->video_mode);
\r
568 mipi_dsih_hal_dpi_hline(instance, (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
569 mipi_dsih_hal_dpi_hbp(instance, ((video_params->h_back_porch_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
570 mipi_dsih_hal_dpi_hsa(instance, ((video_params->h_sync_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
571 mipi_dsih_hal_dpi_vactive(instance, video_params->v_active_lines);
\r
572 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
573 mipi_dsih_hal_dpi_vbp(instance, video_params->v_back_porch_lines);
\r
574 mipi_dsih_hal_dpi_vsync(instance, video_params->v_sync_lines);
\r
575 mipi_dsih_hal_dpi_hsync_pol(instance, !video_params->h_polarity);
\r
576 mipi_dsih_hal_dpi_vsync_pol(instance, !video_params->v_polarity);
\r
577 mipi_dsih_hal_dpi_dataen_pol(instance, !video_params->data_en_polarity);
\r
579 hs_timeout = ((video_params->h_total_pixels * video_params->v_active_lines) + (DSIH_PIXEL_TOLERANCE * bytes_per_pixel_x100) / 100);
\r
580 for (counter = 0x80; (counter < hs_timeout) && (counter > 2); counter--)
\r
582 if ((hs_timeout % counter) == 0)
\r
584 mipi_dsih_hal_timeout_clock_division(instance, counter);
\r
585 mipi_dsih_hal_lp_rx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
586 mipi_dsih_hal_hs_tx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
590 /* TX_ESC_CLOCK_DIV must be less than 20000KHz */
\r
591 // mipi_dsih_hal_tx_escape_division(instance, 6);
\r
592 mipi_dsih_set_lp_clock(instance);
\r
593 /* video packetisation */
\r
594 if (video_params->video_mode == VIDEO_BURST_WITH_SYNC_PULSES)
\r
597 mipi_dsih_hal_dpi_null_packet_en(instance, 0);
\r
598 mipi_dsih_hal_dpi_multi_packet_en(instance, 0);
\r
599 err_code = mipi_dsih_hal_dpi_null_packet_size(instance, 0);
\r
600 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, 1);
\r
601 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
602 if (err_code != OK)
\r
606 /* BURST by default, returns to LP during ALL empty periods - energy saving */
\r
607 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
608 #if (defined(CONFIG_SC8830) ||defined(CONFIG_SC9630)) && defined(CONFIG_LCD_720P)
\r
609 mipi_dsih_hal_dpi_lp_during_hbp(instance, 0);//forbit return to lp during hbp
\r
611 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
613 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
614 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
615 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
616 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
619 if (instance->log_info != 0)
\r
621 instance->log_info("burst video");
\r
622 instance->log_info("h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
623 instance->log_info("video_size %ld", video_size);
\r
629 /* non burst transmission */
\r
630 null_packet_size = 0;
\r
631 /* bytes to be sent - first as one chunk */
\r
632 bytes_per_chunk = (bytes_per_pixel_x100 * video_params->h_active_pixels) / 100 + VIDEO_PACKET_OVERHEAD;
\r
633 /* bytes being received through the DPI interface per byte clock cycle */
\r
634 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
635 /* check if the in pixels actually fit on the DSI link */
\r
636 if (total_bytes >= bytes_per_chunk)
\r
638 chunk_overhead = total_bytes - bytes_per_chunk;
\r
639 /* overhead higher than 1 -> enable multi packets */
\r
640 if (chunk_overhead > 1)
\r
642 /* MULTI packets */
\r
643 for (video_size = video_size_step; video_size < video_params->h_active_pixels; video_size += video_size_step)
\r
645 /* determine no of chunks */
\r
646 if ((((video_params->h_active_pixels * PRECISION_FACTOR) / video_size) % PRECISION_FACTOR) == 0)
\r
648 no_of_chunks = video_params->h_active_pixels / video_size;
\r
649 bytes_per_chunk = (bytes_per_pixel_x100 * video_size) / 100 + VIDEO_PACKET_OVERHEAD;
\r
650 if (total_bytes >= (bytes_per_chunk * no_of_chunks))
\r
652 bytes_left = total_bytes - (bytes_per_chunk * no_of_chunks);
\r
657 /* prevent overflow (unsigned - unsigned) */
\r
658 if (bytes_left > (NULL_PACKET_OVERHEAD * no_of_chunks))
\r
660 null_packet_size = (bytes_left - (NULL_PACKET_OVERHEAD * no_of_chunks)) / no_of_chunks;
\r
661 if (null_packet_size > MAX_NULL_SIZE)
\r
663 /* avoid register overflow */
\r
664 null_packet_size = MAX_NULL_SIZE;
\r
670 /* no multi packets */
\r
674 if (instance->log_info != 0)
\r
676 instance->log_info("no multi no null video");
\r
677 instance->log_info("h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
678 instance->log_info("video_size %ld", video_size);
\r
680 /************************/
\r
682 /* video size must be a multiple of 4 when not 18 loosely */
\r
683 for (video_size = video_params->h_active_pixels; (video_size % video_size_step) != 0; video_size++)
\r
691 instance->log_error("resolution cannot be sent to display through current settings");
\r
692 err_code = ERR_DSI_OVERFLOW;
\r
695 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, no_of_chunks);
\r
696 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
697 err_code = err_code? err_code: mipi_dsih_hal_dpi_null_packet_size(instance, null_packet_size);
\r
698 mipi_dsih_hal_dpi_null_packet_en(instance, null_packet_size > 0? 1: 0);
\r
699 mipi_dsih_hal_dpi_multi_packet_en(instance, (no_of_chunks > 1)? 1: 0);
\r
702 if (instance->log_info != 0)
\r
704 instance->log_info("total_bytes %d", total_bytes);
\r
705 instance->log_info("bytes_per_chunk %d", bytes_per_chunk);
\r
706 instance->log_info("bytes left %d", bytes_left);
\r
707 instance->log_info("null packets %d", null_packet_size);
\r
708 instance->log_info("chunks %ld", no_of_chunks);
\r
709 instance->log_info("video_size %ld", video_size);
\r
711 /************************/
\r
713 mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel);
\r
714 mipi_dsih_dphy_no_of_lanes(&(instance->phy_instance), video_params->no_of_lanes);
\r
715 /* enable high speed clock */
\r
716 // mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1);//jessica, panel not init yet, could not set to hs, or result in err to some panel
\r
720 * Send a DCS write command
\r
721 * It sends the User Command Set commands listed in the DCS specification and
\r
722 * not the Manufacturer Command Set. To send the Manufacturer Commands use the
\r
723 * packet on the generic packets sending function
\r
724 * function sets the packet data type automatically
\r
725 * @param instance pointer to structure holding the DSI Host core information
\r
726 * @param vc destination virtual channel
\r
727 * @param params byte-addressed array of command parameters, including the
\r
729 * @param param_length length of the above array
\r
730 * @return error code
\r
731 * @note this function has an active delay to wait for the buffer to clear.
\r
732 * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time
\r
734 dsih_error_t mipi_dsih_dcs_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
736 uint8_t packet_type = 0;
\r
740 return ERR_DSI_OUT_OF_BOUND;
\r
743 if (param_length > 2)
\r
762 packet_type = 0x05; /* DCS short write no param */
\r
768 packet_type = 0x15; /* DCS short write 1 param */
\r
779 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
782 if (instance->log_error != 0)
\r
784 instance->log_error("invalid DCS command");
\r
786 return ERR_DSI_INVALID_COMMAND;
\r
789 switch(param_length)
\r
792 packet_type = 0x05; /* DCS short write no param */
\r
795 packet_type = 0x15; /* DCS short write 1 param */
\r
798 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
802 return mipi_dsih_gen_wr_packet(instance, vc, packet_type, params, param_length);
\r
805 * Enable command mode
\r
806 * - This function shall be explicitly called before commands are send if they
\r
807 * are to be sent in command mode and not interlaced with video
\r
808 * - If video mode is ON, it will be turned off automatically
\r
809 * @param instance pointer to structure holding the DSI Host core information
\r
810 * @param en enable/disable
\r
812 void mipi_dsih_cmd_mode(dsih_ctrl_t * instance, int en)
\r
819 if (instance->status == INITIALIZED)
\r
821 mipi_dsih_hal_gen_cmd_mode_en(instance, en);
\r
824 if (instance->log_error != 0)
\r
826 instance->log_error("invalid instance");
\r
830 * Enable video mode
\r
831 * - If command mode is ON, it will be turned off automatically
\r
832 * @param instance pointer to structure holding the DSI Host core information
\r
833 * @param en enable/disable
\r
835 void mipi_dsih_video_mode(dsih_ctrl_t * instance, int en)
\r
842 if (instance->status == INITIALIZED)// tianci need change
\r
844 mipi_dsih_hal_dpi_video_mode_en(instance, en);
\r
847 if (instance->log_error != 0)
\r
849 instance->log_error("invalid instance");
\r
853 * Get the current active mode
\r
855 * - 2 DPI video mode
\r
857 int mipi_dsih_active_mode(dsih_ctrl_t * instance)
\r
859 if (mipi_dsih_hal_gen_is_cmd_mode(instance))
\r
863 else if (mipi_dsih_hal_dpi_is_video_mode(instance))
\r
870 * Send a generic write command
\r
871 * @param instance pointer to structure holding the DSI Host core information
\r
872 * @param vc destination virtual channel
\r
873 * @param params byte-addressed array of command parameters
\r
874 * @param param_length length of the above array
\r
875 * @return error code
\r
876 * @note this function has an active delay to wait for the buffer to clear.
\r
877 * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time
\r
879 dsih_error_t mipi_dsih_gen_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
881 uint8_t data_type = 0;
\r
882 switch(param_length)
\r
897 return mipi_dsih_gen_wr_packet(instance, vc, data_type, params, param_length);
\r
900 * Send a packet on the generic interface
\r
901 * @param instance pointer to structure holding the DSI Host core information
\r
902 * @param vc destination virtual channel
\r
903 * @param data_type type of command, inserted in first byte of header
\r
904 * @param params byte array of command parameters
\r
905 * @param param_length length of the above array
\r
906 * @return error code
\r
907 * @note this function has an active delay to wait for the buffer to clear.
\r
908 * The delay is limited to:
\r
909 * (param_length / 4) x DSIH_FIFO_ACTIVE_WAIT x register access time
\r
910 * @note the controller restricts the sending of .
\r
911 * This function will not be able to send Null and Blanking packets due to
\r
912 * controller restriction
\r
914 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
916 dsih_error_t err_code = OK;
\r
917 /* active delay iterator */
\r
922 /* holds padding bytes needed */
\r
923 int compliment_counter = 0;
\r
924 uint8_t* payload = 0;
\r
925 /* temporary variable to arrange bytes into words */
\r
927 uint16_t word_count = 0;
\r
930 return ERR_DSI_INVALID_INSTANCE;
\r
932 if (instance->status != INITIALIZED)
\r
934 return ERR_DSI_INVALID_INSTANCE;
\r
936 if ((params == 0) && (param_length != 0)) /* pointer NULL */
\r
938 return ERR_DSI_OUT_OF_BOUND;
\r
940 if (param_length > 2)
\r
942 /* long packet - write word count to header, and the rest to payload */
\r
943 payload = params + (2 * sizeof(params[0]));
\r
944 word_count = (params[1] << 8) | params[0];
\r
945 if ((param_length - 2) < word_count)
\r
947 if (instance->log_error != 0)
\r
949 instance->log_error("sent > input payload. complemented with zeroes");
\r
951 compliment_counter = (param_length - 2) - word_count;
\r
953 else if ((param_length - 2) > word_count)
\r
955 if (instance->log_error != 0)
\r
957 instance->log_error("Overflow - input > sent. payload truncated");
\r
960 for (i = 0; i < (param_length - 2); i += j)
\r
963 for (j = 0; (j < 4) && ((j + i) < (param_length - 2)); j++)
\r
965 /* temp = (payload[i + 3] << 24) | (payload[i + 2] << 16) | (payload[i + 1] << 8) | payload[i]; */
\r
966 temp |= payload[i + j] << (j * 8);
\r
968 /* check if payload Tx fifo is not full */
\r
969 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
971 if (!mipi_dsih_hal_gen_packet_payload(instance, temp))
\r
976 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
978 return ERR_DSI_TIMEOUT;
\r
981 /* if word count entered by the user more than actual parameters received
\r
982 * fill with zeroes - a fail safe mechanism, otherwise controller will
\r
983 * want to send data from an empty buffer */
\r
984 for (i = 0; i < compliment_counter; i++)
\r
986 /* check if payload Tx fifo is not full */
\r
987 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
989 if (!mipi_dsih_hal_gen_packet_payload(instance, 0x00))
\r
994 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
996 return ERR_DSI_TIMEOUT;
\r
1000 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
1002 /* check if payload Tx fifo is not full */
\r
1003 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
1005 if (param_length == 0)
\r
1007 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, 0x0);
\r
1009 else if (param_length == 1)
\r
1011 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, params[0]);
\r
1015 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, params[1], params[0]);
\r
1020 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
1022 err_code = ERR_DSI_TIMEOUT;
\r
1027 * Send a DCS READ command to peripheral
\r
1028 * function sets the packet data type automatically
\r
1029 * @param instance pointer to structure holding the DSI Host core information
\r
1030 * @param vc destination virtual channel
\r
1031 * @param command DCS code
\r
1032 * @param bytes_to_read no of bytes to read (expected to arrive at buffer)
\r
1033 * @param read_buffer pointer to 8-bit array to hold the read buffer words
\r
1034 * return read_buffer_length
\r
1035 * @note this function has an active delay to wait for the buffer to clear.
\r
1036 * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT
\r
1037 * (waiting for command buffer, and waiting for receiving)
\r
1038 * @note this function will enable BTA
\r
1040 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
1042 if (instance == 0)
\r
1046 if (instance->status != INITIALIZED)
\r
1066 /* COMMAND_TYPE 0x06 - DCS Read no params refer to DSI spec p.47 */
\r
1067 return mipi_dsih_gen_rd_packet(instance, vc, 0x06, 0x0, command, bytes_to_read, read_buffer);
\r
1069 if (instance->log_error != 0)
\r
1071 instance->log_error("invalid DCS command");
\r
1078 * Send Generic READ command to peripheral
\r
1079 * - function sets the packet data type automatically
\r
1080 * @param instance pointer to structure holding the DSI Host core information
\r
1081 * @param vc destination virtual channel
\r
1082 * @param params byte array of command parameters
\r
1083 * @param param_length length of the above array
\r
1084 * @param bytes_to_read no of bytes to read (expected to arrive at buffer)
\r
1085 * @param read_buffer pointer to 8-bit array to hold the read buffer words
\r
1086 * return read_buffer_length
\r
1087 * @note this function has an active delay to wait for the buffer to clear.
\r
1088 * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT
\r
1089 * (waiting for command buffer, and waiting for receiving)
\r
1090 * @note this function will enable BTA
\r
1092 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
1094 uint8_t data_type = 0;
\r
1095 if (instance == 0)
\r
1099 if (instance->status != INITIALIZED)
\r
1103 switch(param_length)
\r
1107 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, 0x00, bytes_to_read, read_buffer);
\r
1110 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, params[0], bytes_to_read, read_buffer);
\r
1113 return mipi_dsih_gen_rd_packet(instance, vc, data_type, params[1], params[0], bytes_to_read, read_buffer);
\r
1119 * Send READ packet to peripheral using the generic interface
\r
1120 * This will force command mode and stop video mode (because of BTA)
\r
1121 * @param instance pointer to structure holding the DSI Host core information
\r
1122 * @param vc destination virtual channel
\r
1123 * @param data_type generic command type
\r
1124 * @param lsb_byte first command parameter
\r
1125 * @param msb_byte second command parameter
\r
1126 * @param bytes_to_read no of bytes to read (expected to arrive at buffer)
\r
1127 * @param read_buffer pointer to 8-bit array to hold the read buffer words
\r
1128 * return read_buffer_length
\r
1129 * @note this function has an active delay to wait for the buffer to clear.
\r
1130 * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT
\r
1131 * (waiting for command buffer, and waiting for receiving)
\r
1132 * @note this function will enable BTA
\r
1134 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
1136 dsih_error_t err_code = OK;
\r
1140 int last_count = 0;
\r
1141 uint32_t temp[1] = {0};
\r
1142 if (instance == 0)
\r
1146 if (instance->status != INITIALIZED)
\r
1150 if (bytes_to_read < 1)
\r
1154 if (read_buffer == 0)
\r
1158 /* make sure command mode is on */
\r
1159 mipi_dsih_cmd_mode(instance, 1);
\r
1160 /* make sure receiving is enabled */
\r
1161 mipi_dsih_hal_bta_en(instance, 1);
\r
1162 /* listen to the same virtual channel as the one sent to */
\r
1163 mipi_dsih_hal_gen_rd_vc(instance, vc);
\r
1164 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
1166 /* check if payload Tx fifo is not full */
\r
1167 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
1169 mipi_dsih_hal_gen_packet_header(instance, vc, data_type, msb_byte, lsb_byte);
\r
1173 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
1175 if (instance->log_error != 0)
\r
1177 instance->log_error("tx rd command timed out");
\r
1181 /* loop for the number of words to be read */
\r
1182 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
1184 /* check if command transaction is done */
\r
1185 if (!mipi_dsih_hal_gen_rd_cmd_busy(instance))
\r
1187 if (!mipi_dsih_hal_gen_read_fifo_empty(instance))
\r
1189 for (counter = 0; (!mipi_dsih_hal_gen_read_fifo_empty(instance)); counter += 4)
\r
1191 err_code = mipi_dsih_hal_gen_read_payload(instance, temp);
\r
1196 if (counter < bytes_to_read)
\r
1198 for (i = 0; i < 4; i++)
\r
1200 if ((counter + i) < bytes_to_read)
\r
1202 /* put 32 bit temp in 4 bytes of buffer passed by user*/
\r
1203 read_buffer[counter + i] = (uint8_t)(temp[0] >> (i * 8));
\r
1204 last_count = i + counter;
\r
1208 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
1210 last_count = i + counter;
\r
1217 last_count = counter;
\r
1218 for (i = 0; i < 4; i++)
\r
1220 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
1222 last_count = i + counter;
\r
1227 return last_count + 1;
\r
1231 if (instance->log_error != 0)
\r
1233 instance->log_error("rx buffer empty");
\r
1239 if (instance->log_error != 0)
\r
1241 instance->log_error("rx command timed out");
\r
1246 * Dump values stored in the DSI host core registers
\r
1247 * @param instance pointer to structure holding the DSI Host core information
\r
1248 * @param all whether to dump all the registers, no register_config array need
\r
1249 * be provided if dump is to standard IO
\r
1250 * @param config array of register_config_t type where addresses and values are
\r
1252 * @param config_length the length of the config array
\r
1253 * @return the number of the registers that were read
\r
1255 uint32_t mipi_dsih_dump_register_configuration(dsih_ctrl_t * instance, int all, register_config_t *config, uint16_t config_length)
\r
1257 uint32_t current = 0;
\r
1258 uint16_t count = 0;
\r
1259 if (instance == 0)
\r
1261 return ERR_DSI_INVALID_INSTANCE;
\r
1263 if (instance->status != INITIALIZED)
\r
1265 return ERR_DSI_INVALID_INSTANCE;
\r
1269 /* dump all registers */
\r
1270 for (current = R_DSI_HOST_VERSION; current <= R_DSI_HOST_PHY_TMR_LPCLK_CFG; count++, current += (R_DSI_HOST_PWR_UP - R_DSI_HOST_VERSION))
\r
1272 if ((config_length == 0) || (config == 0) || count >= config_length)
\r
1274 /* no place to write - write to STD IO */
\r
1275 if (instance->log_info != 0)
\r
1277 instance->log_info("DSI 0x%lX:0x%lX", current, mipi_dsih_read_word(instance, current));
\r
1282 config[count].addr = current;
\r
1283 config[count].data = mipi_dsih_read_word(instance, current);
\r
1291 if (instance->log_error != 0)
\r
1293 instance->log_error("invalid buffer");
\r
1298 for (count = 0; count < config_length; count++)
\r
1300 config[count].data = mipi_dsih_read_word(instance, config[count].addr);
\r
1307 * Write values to DSI host core registers
\r
1308 * @param instance pointer to structure holding the DSI Host core information
\r
1309 * @param config array of register_config_t type where register addresses and
\r
1310 * their new values are stored
\r
1311 * @param config_length the length of the config array
\r
1312 * @return the number of the registers that were written to
\r
1314 uint32_t mipi_dsih_write_register_configuration(dsih_ctrl_t * instance, register_config_t *config, uint16_t config_length)
\r
1316 uint16_t count = 0;
\r
1317 if (instance == 0)
\r
1319 return ERR_DSI_INVALID_INSTANCE;
\r
1321 if (instance->status != INITIALIZED)
\r
1323 return ERR_DSI_INVALID_INSTANCE;
\r
1325 for (count = 0; count < config_length; count++)
\r
1327 mipi_dsih_write_word(instance, config[count].addr, config[count].data);
\r
1332 * Register a handler for a specific event
\r
1333 * - The handler will be called when this specific event occurs
\r
1334 * @param instance pointer to structure holding the DSI Host core information
\r
1335 * @param event enum
\r
1336 * @param handler call back to handler function to handle the event
\r
1337 * @return error code
\r
1339 dsih_error_t mipi_dsih_register_event(dsih_ctrl_t * instance, dsih_event_t event, void (*handler)(dsih_ctrl_t *, void *))
\r
1341 uint32_t mask = 1;
\r
1342 uint32_t temp = 0;
\r
1343 if (event >= DSI_MAX_EVENT)
\r
1345 return ERR_DSI_INVALID_EVENT;
\r
1349 return ERR_DSI_INVALID_HANDLE;
\r
1351 if (instance == 0)
\r
1353 return ERR_DSI_INVALID_INSTANCE;
\r
1355 if (instance->status != INITIALIZED)
\r
1357 return ERR_DSI_INVALID_INSTANCE;
\r
1359 instance->event_registry[event] = handler;
\r
1360 if (event < HS_CONTENTION)
\r
1362 temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff);
\r
1363 temp &= ~(mask << event);
\r
1364 temp |= (0 & mask) << event;
\r
1365 mipi_dsih_hal_int_mask_0(instance, temp);
\r
1369 temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff);
\r
1370 temp &= ~(mask << (event - HS_CONTENTION));
\r
1371 temp |= (0 & mask) << (event - HS_CONTENTION);
\r
1372 mipi_dsih_hal_int_mask_1(instance, temp);
\r
1373 if (event == RX_CRC_ERR)
\r
1375 /* automatically enable CRC reporting */
\r
1376 mipi_dsih_hal_gen_crc_rx_en(instance, 1);
\r
1382 * Clear an already registered event
\r
1383 * - Callback of the handler will be removed
\r
1384 * @param instance pointer to structure holding the DSI Host core information
\r
1385 * @param event enum
\r
1386 * @return error code
\r
1388 dsih_error_t mipi_dsih_unregister_event(dsih_ctrl_t * instance, dsih_event_t event)
\r
1390 uint32_t mask = 1;
\r
1391 uint32_t temp = 0;
\r
1392 if (event >= DSI_MAX_EVENT)
\r
1394 return ERR_DSI_INVALID_EVENT;
\r
1396 if (instance == 0)
\r
1398 return ERR_DSI_INVALID_INSTANCE;
\r
1400 if (instance->status != INITIALIZED)
\r
1402 return ERR_DSI_INVALID_INSTANCE;
\r
1404 instance->event_registry[event] = 0;
\r
1405 if (event < HS_CONTENTION)
\r
1407 temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff);
\r
1408 temp &= ~(mask << event);
\r
1409 temp |= (1 & mask) << event;
\r
1410 mipi_dsih_hal_int_mask_0(instance, temp);
\r
1414 temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff);
\r
1415 temp &= ~(mask << (event - HS_CONTENTION));
\r
1416 temp |= (1 & mask) << (event - HS_CONTENTION);
\r
1417 mipi_dsih_hal_int_mask_1(instance, temp);
\r
1418 if (event == RX_CRC_ERR)
\r
1420 /* automatically disable CRC reporting */
\r
1421 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1427 * Clear all registered events at once
\r
1428 * @param instance pointer to structure holding the DSI Host core information
\r
1429 * @return error code
\r
1431 dsih_error_t mipi_dsih_unregister_all_events(dsih_ctrl_t * instance)
\r
1434 if (instance == 0)
\r
1436 return ERR_DSI_INVALID_INSTANCE;
\r
1438 if (instance->status != INITIALIZED)
\r
1440 return ERR_DSI_INVALID_INSTANCE;
\r
1442 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1444 instance->event_registry[i] = 0;
\r
1446 mipi_dsih_hal_int_mask_0(instance, 0xffffff);
\r
1447 mipi_dsih_hal_int_mask_1(instance, 0xffffff);
\r
1448 /* automatically disable CRC reporting */
\r
1449 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1453 * This event handler shall be called upon receiving any event
\r
1454 * it will call the specific callback (handler) registered for the invoking
\r
1455 * event. Registration is done beforehand using mipi_dsih_register_event
\r
1456 * its signature is void * so it could be OS agnostic (for it to be
\r
1457 * registered in any OS/Interrupt controller)
\r
1458 * @param param pointer to structure holding the DSI Host core information
\r
1459 * @note This function must be registered with the DSI IRQs
\r
1461 void mipi_dsih_event_handler(void * param)
\r
1463 dsih_ctrl_t * instance = (dsih_ctrl_t *)(param);
\r
1465 uint32_t status_0;
\r
1466 uint32_t status_1;
\r
1467 if (instance == 0)
\r
1471 status_0 = mipi_dsih_hal_int_status_0(instance, 0xffffffff);
\r
1472 status_1 = mipi_dsih_hal_int_status_1(instance, 0xffffffff);
\r
1474 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1476 if (instance->event_registry[i] != 0)
\r
1478 if (i < HS_CONTENTION)
\r
1480 if ((status_0 & (1 << i)) != 0)
\r
1482 instance->event_registry[i](instance, &i);
\r
1487 if ((status_1 & (1 << (i - HS_CONTENTION))) != 0)
\r
1489 instance->event_registry[i](instance, &i);
\r
1496 * Reset the DSI Host controller
\r
1497 * - Sends a pulse to the shut down register
\r
1498 * @param instance pointer to structure holding the DSI Host core information
\r
1500 void mipi_dsih_reset_controller(dsih_ctrl_t * instance)
\r
1502 mipi_dsih_hal_power(instance, 0);
\r
1503 mipi_dsih_hal_power(instance, 1);
\r
1506 * Shut down the DSI Host controller
\r
1507 * @param instance pointer to structure holding the DSI Host core information
\r
1508 * @param shutdown (1) power up (0)
\r
1510 void mipi_dsih_shutdown_controller(dsih_ctrl_t * instance, int shutdown)
\r
1512 mipi_dsih_hal_power(instance, !shutdown);
\r
1515 * Reset the PHY module being controlled by the DSI Host controller
\r
1516 * - Sends a pulse to the PPI reset signal
\r
1517 * @param instance pointer to structure holding the DSI Host core information
\r
1519 void mipi_dsih_reset_phy(dsih_ctrl_t * instance)
\r
1521 mipi_dsih_dphy_reset(&(instance->phy_instance), 0);
\r
1522 mipi_dsih_dphy_reset(&(instance->phy_instance), 1);
\r
1525 * Shut down the PHY module being controlled by the DSI Host controller
\r
1526 * @param instance pointer to structure holding the DSI Host core information
\r
1527 * @param shutdown (1) power up (0)
\r
1529 void mipi_dsih_shutdown_phy(dsih_ctrl_t * instance, int shutdown)
\r
1531 mipi_dsih_dphy_shutdown(&(instance->phy_instance), !shutdown);
\r
1534 * Configure the eDPI interface
\r
1535 * - Programs the controller to receive pixels on the DPI interface and send them
\r
1536 * as commands (write memory start and write memory continue) instead of a
\r
1538 * @param instance pointer to structure holding the DSI Host core information
\r
1539 * @param video_params pointer to the command mode video parameters context
\r
1540 * @param send_setup_packets whether to send the setup packets from given info. These are: 1 - set pixel format; 2 - set column address; 3 - set page address
\r
1541 * @return error code
\r
1543 dsih_error_t mipi_dsih_edpi_video(dsih_ctrl_t * instance, dsih_cmd_mode_video_t *video_params, int send_setup_packets)
\r
1545 dsih_error_t err_code = OK;
\r
1546 uint8_t buf[7] = {0};
\r
1547 uint32_t bytes_per_pixel_x100 = 0;
\r
1548 mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel);
\r
1549 mipi_dsih_cmd_mode(instance, 1);
\r
1550 err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding);
\r
1551 /* define whether write memory commands will be sent in LP or HS */
\r
1552 err_code = err_code? err_code: mipi_dsih_hal_dcs_wr_tx_type(instance, 3, video_params->lp); /* long packet*/
\r
1553 if (send_setup_packets)
\r
1555 /* define pixel packing format - 1 param */
\r
1557 /* colour depth: table 6 DCS spec. 3:1| 8:2| 12:3| 16:5| 18:6| 24:7*/
\r
1558 switch (video_params->color_coding)
\r
1573 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 2);
\r
1576 instance->log_error("error setting up command video - colour depth");
\r
1578 /* set column address (left to right) - 4 param */
\r
1579 buf[0] = 0x05; /* cmd length */
\r
1581 buf[2] = 0x2A; /* cmd opcode */
\r
1582 buf[3] = (uint8_t)(video_params->h_start >> 8); /* payload start */
\r
1583 buf[4] = (uint8_t)(video_params->h_start);
\r
1584 buf[5] = (uint8_t)(video_params->h_active_pixels >> 8);
\r
1585 buf[6] = (uint8_t)(video_params->h_active_pixels);
\r
1586 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7);
\r
1589 instance->log_error("error setting up command video - set column address");
\r
1591 /* set page address (top to bottom) 4 - param*/
\r
1592 buf[0] = 0x05; /* cmd length */
\r
1594 buf[2] = 0x2B; /* cmd opcode */
\r
1595 buf[3] = (uint8_t)(video_params->v_start >> 8); /* payload start */
\r
1596 buf[4] = (uint8_t)(video_params->v_start);
\r
1597 buf[5] = (uint8_t)(video_params->v_active_lines >> 8);
\r
1598 buf[6] = (uint8_t)(video_params->v_active_lines);
\r
1599 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7);
\r
1602 instance->log_error("error setting up command video - set page address");
\r
1605 switch (video_params->color_coding)
\r
1607 case COLOR_CODE_16BIT_CONFIG1:
\r
1608 case COLOR_CODE_16BIT_CONFIG2:
\r
1609 case COLOR_CODE_16BIT_CONFIG3:
\r
1610 bytes_per_pixel_x100 = 200;
\r
1612 case COLOR_CODE_18BIT_CONFIG1:
\r
1613 case COLOR_CODE_18BIT_CONFIG2:
\r
1614 bytes_per_pixel_x100 = 225;
\r
1616 case COLOR_CODE_24BIT:
\r
1617 bytes_per_pixel_x100 = 300;
\r
1619 case COLOR_CODE_20BIT_YCC422_LOOSELY:
\r
1620 bytes_per_pixel_x100 = 250;
\r
1622 case COLOR_CODE_24BIT_YCC422:
\r
1623 bytes_per_pixel_x100 = 300;
\r
1625 case COLOR_CODE_16BIT_YCC422:
\r
1626 bytes_per_pixel_x100 = 200;
\r
1628 case COLOR_CODE_30BIT:
\r
1629 bytes_per_pixel_x100 = 375;
\r
1631 case COLOR_CODE_36BIT:
\r
1632 bytes_per_pixel_x100 = 450;
\r
1634 case COLOR_CODE_12BIT_YCC420:
\r
1635 bytes_per_pixel_x100 = 150;
\r
1638 if (instance->log_error != 0)
\r
1640 instance->log_error("invalid color coding");
\r
1642 err_code = ERR_DSI_COLOR_CODING;
\r
1645 if (video_params->te)
\r
1647 mipi_dsih_hal_bta_en(instance, video_params->te);
\r
1648 /* enable tearing effect */
\r
1649 mipi_dsih_tear_effect_ack(instance, video_params->te);
\r
1651 err_code = mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 1);
\r
1653 mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1);
\r
1654 if ((((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100) > video_params->h_active_pixels)
\r
1656 mipi_dsih_hal_edpi_max_allowed_size(instance, video_params->h_active_pixels);
\r
1660 mipi_dsih_hal_edpi_max_allowed_size(instance, (((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100));
\r
1665 /* PRESP Time outs */
\r
1667 * Timeout for peripheral (for controller to stay still) after LP data
\r
1668 * transmission write requests
\r
1669 * @param instance pointer to structure holding the DSI Host core information
\r
1670 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1671 * link still, after sending a low power write operation. This period is
\r
1672 * measured in cycles of lanebyteclk
\r
1674 void mipi_dsih_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1676 mipi_dsih_hal_presp_timeout_low_power_write(instance, no_of_byte_cycles);
\r
1679 * Timeout for peripheral (for controller to stay still) after LP data
\r
1680 * transmission read requests
\r
1681 * @param instance pointer to structure holding the DSI Host core information
\r
1682 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1683 * link still, after sending a low power read operation. This period is
\r
1684 * measured in cycles of lanebyteclk
\r
1686 void mipi_dsih_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1688 mipi_dsih_hal_presp_timeout_low_power_read(instance, no_of_byte_cycles);
\r
1691 * Timeout for peripheral (for controller to stay still) after HS data
\r
1692 * transmission write requests
\r
1693 * @param instance pointer to structure holding the DSI Host core information
\r
1694 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1695 * link still, after sending a high-speed write operation. This period is
\r
1696 * measured in cycles of lanebyteclk
\r
1698 void mipi_dsih_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1700 mipi_dsih_hal_presp_timeout_high_speed_write(instance, no_of_byte_cycles);
\r
1703 * Timeout for peripheral between HS data transmission read requests
\r
1704 * @param instance pointer to structure holding the DSI Host core information
\r
1705 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1706 * link still, after sending a high-speed read operation. This period is
\r
1707 * measured in cycles of lanebyteclk
\r
1709 void mipi_dsih_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1711 mipi_dsih_hal_presp_timeout_high_speed_read(instance, no_of_byte_cycles);
\r
1714 * Timeout for peripheral (for controller to stay still) after bus turn around
\r
1715 * @param instance pointer to structure holding the DSI Host core information
\r
1716 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1717 * link still, after sending a BTA operation. This period is
\r
1718 * measured in cycles of lanebyteclk
\r
1720 void mipi_dsih_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1722 mipi_dsih_hal_presp_timeout_bta(instance, no_of_byte_cycles);
\r
1724 uint16_t mipi_dsih_check_dbi_fifos_state(dsih_ctrl_t * instance)
\r
1727 while( cnt < 5000 && mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15)
\r
1731 return (mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15) ? -1 : 1;
\r
1733 uint16_t mipi_dsih_check_ulpm_mode(dsih_ctrl_t * instance)
\r
1735 return (mipi_dsih_read_word(instance, R_DSI_HOST_PHY_STATUS) != 0x1528) ? -1 : 1;
\r