1 #include "mipi_dsih_api.h"
\r
2 #include "mipi_dsih_hal.h"
\r
3 #include "mipi_dsih_dphy.h"
\r
4 #include <linux/delay.h>
\r
6 /* whether to get debug messages (1) or not (0) */
\r
9 #define PRECISION_FACTOR 1000
\r
10 #define VIDEO_PACKET_OVERHEAD 6
\r
11 #define NULL_PACKET_OVERHEAD 6
\r
12 #define SHORT_PACKET 4
\r
13 #define BLANKING_PACKET 6
\r
14 /** Version supported by this driver */
\r
15 static const uint32_t mipi_dsih_supported_versions[] = {0x3132302A, 0x3132312A};
\r
16 static const uint32_t mipi_dsih_no_of_versions = sizeof(mipi_dsih_supported_versions) / sizeof(uint32_t);
\r
19 * Open controller instance
\r
20 * - Check if driver is compatible with core version
\r
21 * - Check if instance context data structure is not NULL
\r
22 * - Bring up PHY for any transmissions in low power
\r
23 * + Includes programming PLL to DEFAULT_BYTE_CLOCK
\r
24 * - Bring up controller and perform initial configuration
\r
25 * + Includes start all commands transmision in LP
\r
26 * + Controller will not turn the bus around after commands
\r
27 * + program counters
\r
28 * @param instance pointer to structure holding the DSI Host core information
\r
29 * @return dsih_error_t
\r
30 * @note this function must be called before any other function in this API
\r
32 dsih_error_t mipi_dsih_open(dsih_ctrl_t * instance)
\r
34 dsih_error_t err = OK;
\r
35 uint32_t version = 0;
\r
40 return ERR_DSI_INVALID_INSTANCE;
\r
42 else if ((instance->core_read_function == 0) || (instance->core_write_function == 0))
\r
44 return ERR_DSI_INVALID_IO;
\r
46 else if (instance->status == INITIALIZED)
\r
48 return ERR_DSI_INVALID_INSTANCE;
\r
50 else if (mipi_dsih_dphy_open(&(instance->phy_instance)))
\r
52 return ERR_DSI_PHY_INVALID;
\r
56 instance->status = NOT_INITIALIZED;
\r
57 version = mipi_dsih_hal_get_version(instance);
\r
58 for (i = 0; i < mipi_dsih_no_of_versions; i++)
\r
60 if (version == mipi_dsih_supported_versions[i])
\r
65 /* no matching supported version has been found*/
\r
66 if (i >= mipi_dsih_no_of_versions)
\r
68 if (instance->log_info != 0)
\r
70 instance->log_info("sprdfb: driver does not support this core version 0x%lX", version);
\r
72 return ERR_DSI_CORE_INCOMPATIBLE;
\r
75 mipi_dsih_hal_power(instance, 0);
\r
76 //mipi_dsih_hal_power(instance, 0);//Jessica
\r
77 //mipi_dsih_hal_power(instance, 1);//Jessica
\r
78 mipi_dsih_hal_dpi_color_mode_pol(instance, !instance->color_mode_polarity);
\r
79 mipi_dsih_hal_dpi_shut_down_pol(instance, !instance->shut_down_polarity);
\r
80 //err = mipi_dsih_phy_hs2lp_config(instance, instance->max_hs_to_lp_cycles);
\r
81 //err |= mipi_dsih_phy_lp2hs_config(instance, instance->max_lp_to_hs_cycles);
\r
82 mipi_dsih_hal_int_mask_0(instance, 0xffffff);
\r
83 mipi_dsih_hal_int_mask_1(instance, 0xffffff);
\r
84 err = mipi_dsih_phy_bta_time(instance, instance->max_bta_cycles);
\r
87 return ERR_DSI_OVERFLOW;
\r
89 /* by default, return to LP during ALL, unless otherwise specified*/
\r
90 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
91 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
92 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
93 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
94 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
95 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
96 /* by default, all commands are sent in LP */
\r
97 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, 1);
\r
98 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, 1);
\r
99 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, 1); /* long packet*/
\r
100 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, 1);
\r
101 /*Jessica add to support max rd packet size command*/
\r
102 mipi_dsih_hal_max_rd_packet_size_type(instance, 1);
\r
103 mipi_dsih_hal_gen_wr_tx_type(instance, 0, 1);
\r
104 mipi_dsih_hal_gen_wr_tx_type(instance, 1, 1);
\r
105 mipi_dsih_hal_gen_wr_tx_type(instance, 2, 1);
\r
106 mipi_dsih_hal_gen_wr_tx_type(instance, 3, 1); /* long packet*/
\r
107 mipi_dsih_hal_gen_rd_tx_type(instance, 0, 1);
\r
108 mipi_dsih_hal_gen_rd_tx_type(instance, 1, 1);
\r
109 mipi_dsih_hal_gen_rd_tx_type(instance, 2, 1);
\r
110 /* by default, RX_VC = 0, NO EOTp, EOTn, BTA, ECC rx and CRC rx */
\r
111 mipi_dsih_hal_gen_rd_vc(instance, 0);
\r
112 mipi_dsih_hal_gen_eotp_rx_en(instance, 0);
\r
113 mipi_dsih_hal_gen_eotp_tx_en(instance, 0);
\r
114 mipi_dsih_hal_bta_en(instance, 0);
\r
115 mipi_dsih_hal_gen_ecc_rx_en(instance, 0);
\r
116 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
117 //mipi_dsih_hal_power(instance, 0);//Jessica
\r
118 mipi_dsih_hal_power(instance, 1);//Jessica
\r
120 /* dividing by 6 is aimed for max PHY frequency, 1GHz */
\r
121 mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessica
\r
122 instance->status = INITIALIZED;
\r
123 /* initialize pll so escape clocks could be generated at 864MHz, 1 lane */
\r
124 /* however the high speed clock will not be requested */
\r
125 //err = mipi_dsih_dphy_configure(&(instance->phy_instance), 1, DEFAULT_BYTE_CLOCK);
\r
129 * Close DSI Host driver
\r
130 * - Free up resources and shutdown host controller and PHY
\r
131 * @param instance pointer to structure holding the DSI Host core information
\r
132 * @return dsih_error_t
\r
134 dsih_error_t mipi_dsih_close(dsih_ctrl_t * instance)
\r
138 return ERR_DSI_INVALID_INSTANCE;
\r
140 if (instance->status != INITIALIZED)
\r
142 return ERR_DSI_INVALID_INSTANCE;
\r
144 mipi_dsih_hal_int_mask_0(instance, 0xffffff);
\r
145 mipi_dsih_hal_int_mask_1(instance, 0xffffff);
\r
146 mipi_dsih_dphy_close(&(instance->phy_instance));
\r
147 mipi_dsih_hal_power(instance, 0);
\r
148 instance->status = NOT_INITIALIZED;
\r
152 * Enable return to low power mode inside video periods when timing allows
\r
153 * @param instance pointer to structure holding the DSI Host core information
\r
154 * @param hfp allow to return to lp inside horizontal front porch pixels
\r
155 * @param hbp allow to return to lp inside horizontal back porch pixels
\r
156 * @param vactive allow to return to lp inside vertical active lines
\r
157 * @param vfp allow to return to lp inside vertical front porch lines
\r
158 * @param vbp allow to return to lp inside vertical back porch lines
\r
159 * @param vsync allow to return to lp inside vertical sync lines
\r
161 void mipi_dsih_allow_return_to_lp(dsih_ctrl_t * instance, int hfp, int hbp, int vactive, int vfp, int vbp, int vsync)
\r
168 if (instance->status == INITIALIZED)
\r
170 mipi_dsih_hal_dpi_lp_during_hfp(instance, hfp);
\r
171 mipi_dsih_hal_dpi_lp_during_hbp(instance, hbp);
\r
172 mipi_dsih_hal_dpi_lp_during_vactive(instance, vactive);
\r
173 mipi_dsih_hal_dpi_lp_during_vfp(instance, vfp);
\r
174 mipi_dsih_hal_dpi_lp_during_vbp(instance, vbp);
\r
175 mipi_dsih_hal_dpi_lp_during_vsync(instance, vsync);
\r
178 if (instance->log_error != 0)
\r
180 instance->log_error("sprdfb: [mipi_dsih_allow_return_to_lp] invalid instance");
\r
185 * Set DCS command packet transmission to low power
\r
186 * @param instance pointer to structure holding the DSI Host core information
\r
187 * @param long_write command packets
\r
188 * @param short_write command packets with none and one parameters
\r
189 * @param short_read command packets with none parameters
\r
191 void mipi_dsih_dcs_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
198 if (instance->status == INITIALIZED)
\r
200 mipi_dsih_hal_dcs_wr_tx_type(instance, 0, short_write);
\r
201 mipi_dsih_hal_dcs_wr_tx_type(instance, 1, short_write);
\r
202 mipi_dsih_hal_dcs_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
203 mipi_dsih_hal_dcs_rd_tx_type(instance, 0, short_read);
\r
206 if (instance->log_error != 0)
\r
208 instance->log_error("sprdfb: [mipi_dsih_dcs_cmd_lp_transmission] invalid instance");
\r
213 * Set Generic interface packet transmission to low power
\r
214 * @param instance pointer to structure holding the DSI Host core information
\r
215 * @param long_write command packets
\r
216 * @param short_write command packets with none, one and two parameters
\r
217 * @param short_read command packets with none, one and two parameters
\r
219 void mipi_dsih_gen_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read)
\r
226 if (instance->status == INITIALIZED)
\r
228 mipi_dsih_hal_gen_wr_tx_type(instance, 0, short_write);
\r
229 mipi_dsih_hal_gen_wr_tx_type(instance, 1, short_write);
\r
230 mipi_dsih_hal_gen_wr_tx_type(instance, 2, short_write);
\r
231 mipi_dsih_hal_gen_wr_tx_type(instance, 3, long_write); /* long packet*/
\r
232 mipi_dsih_hal_gen_rd_tx_type(instance, 0, short_read);
\r
233 mipi_dsih_hal_gen_rd_tx_type(instance, 1, short_read);
\r
234 mipi_dsih_hal_gen_rd_tx_type(instance, 2, short_read);
\r
237 if (instance->log_error != 0)
\r
239 instance->log_error("sprdfb: [mipi_dsih_gen_cmd_lp_transmission] invalid instance");
\r
243 /* packet handling */
\r
245 * Enable all receiving activities (applying a Bus Turn Around).
\r
246 * - Disabling using this function will stop all acknowledges by the
\r
247 * peripherals and no interrupts from low-level protocol error reporting
\r
248 * will be able to rise.
\r
249 * - Enabling any receiving function (command or frame ACKs, ECC,
\r
250 * tear effect ACK or EoTp receiving) will enable this automatically,
\r
251 * but it must be EXPLICITLY be disabled to disabled all kinds of
\r
252 * receiving functionality.
\r
253 * @param instance pointer to structure holding the DSI Host core information
\r
254 * @param enable or disable
\r
255 * @return error code
\r
257 dsih_error_t mipi_dsih_enable_rx(dsih_ctrl_t * instance, int enable)
\r
259 mipi_dsih_hal_bta_en(instance, enable);
\r
263 * Enable command packet acknowledges by the peripherals
\r
264 * - For interrupts to rise the monitored event must be registered
\r
265 * using the event_register function
\r
266 * @param instance pointer to structure holding the DSI Host core information
\r
267 * @param enable or disable
\r
268 * @return error code
\r
270 dsih_error_t mipi_dsih_peripheral_ack(dsih_ctrl_t * instance, int enable)
\r
274 if (instance->status == INITIALIZED)
\r
276 mipi_dsih_hal_cmd_ack_en(instance, enable);
\r
279 mipi_dsih_hal_bta_en(instance, 1);
\r
284 return ERR_DSI_INVALID_INSTANCE;
\r
287 * Enable tearing effect acknowledges by the peripherals (wait for TE)
\r
288 * - It enables the following from the DSI specification
\r
289 * "Since the timing of a TE event is, by definition, unknown to the host
\r
290 * processor, the host processor shall give bus possession to the display
\r
291 * module and then wait for up to one video frame period for the TE response.
\r
292 * During this time, the host processor cannot send new commands, or requests
\r
293 * to the display module, because it does not have bus possession."
\r
294 * @param instance pointer to structure holding the DSI Host core information
\r
295 * @param enable or disable
\r
296 * @return error code
\r
298 dsih_error_t mipi_dsih_tear_effect_ack(dsih_ctrl_t * instance, int enable)
\r
302 if (instance->status == INITIALIZED)
\r
304 mipi_dsih_hal_tear_effect_ack_en(instance, enable);
\r
307 mipi_dsih_hal_bta_en(instance, 1);
\r
312 return ERR_DSI_INVALID_INSTANCE;
\r
315 * Enable the receiving of EoT packets at the end of LS transmission.
\r
316 * @param instance pointer to structure holding the DSI Host core information
\r
317 * @param enable or disable
\r
318 * @return error code
\r
320 dsih_error_t mipi_dsih_eotp_rx(dsih_ctrl_t * instance, int enable)
\r
324 if (instance->status == INITIALIZED)
\r
326 mipi_dsih_hal_gen_eotp_rx_en(instance, enable);
\r
329 mipi_dsih_hal_bta_en(instance, 1);
\r
334 return ERR_DSI_INVALID_INSTANCE;
\r
337 * Enable the listening to ECC bytes. This allows for recovering from
\r
338 * 1 bit errors. To report ECC events, the ECC events should be registered
\r
339 * @param instance pointer to structure holding the DSI Host core information
\r
340 * @param enable or disable
\r
341 * @return error code
\r
343 dsih_error_t mipi_dsih_ecc_rx(dsih_ctrl_t * instance, int enable)
\r
347 if (instance->status == INITIALIZED)
\r
349 mipi_dsih_hal_gen_ecc_rx_en(instance, enable);
\r
352 mipi_dsih_hal_bta_en(instance, 1);
\r
357 return ERR_DSI_INVALID_INSTANCE;
\r
360 * Enable the sending of EoT (End of Transmission) packets at the end of HS
\r
361 * transmission. It was made optional in the DSI spec. for retro-compatibility.
\r
362 * @param instance pointer to structure holding the DSI Host core information
\r
363 * @param enable or disable
\r
364 * @return error code
\r
366 dsih_error_t mipi_dsih_eotp_tx(dsih_ctrl_t * instance, int enable)
\r
370 if (instance->status == INITIALIZED)
\r
372 mipi_dsih_hal_gen_eotp_tx_en(instance, enable);
\r
376 return ERR_DSI_INVALID_INSTANCE;
\r
379 * Configure DPI video interface
\r
380 * - If not in burst mode, it will compute the video and null packet sizes
\r
381 * according to necessity
\r
382 * - Configure timers for data lanes and/or clock lane to return to LP when
\r
383 * bandwidth is not filled by data
\r
384 * @param instance pointer to structure holding the DSI Host core information
\r
385 * @param video_params pointer to video stream-to-send information
\r
386 * @return error code
\r
388 dsih_error_t mipi_dsih_dpi_video(dsih_ctrl_t * instance, dsih_dpi_video_t * video_params)
\r
390 dsih_error_t err_code = OK;
\r
391 uint16_t bytes_per_pixel_x100 = 0; /* bpp x 100 because it can be 2.25 */
\r
392 uint16_t video_size = 0;
\r
393 uint32_t ratio_clock_xPF = 0; /* holds dpi clock/byte clock times precision factor */
\r
394 uint16_t null_packet_size = 0;
\r
395 uint8_t video_size_step = 1;
\r
396 uint32_t hs_timeout = 0;
\r
397 uint32_t total_bytes = 0;
\r
398 uint32_t bytes_per_chunk = 0;
\r
399 uint32_t no_of_chunks = 0;
\r
400 uint32_t bytes_left = 0;
\r
401 uint32_t chunk_overhead = 0;
\r
403 /* check DSI controller instance */
\r
404 if ((instance == 0) || (video_params == 0))
\r
406 return ERR_DSI_INVALID_INSTANCE;
\r
408 if (instance->status != INITIALIZED)
\r
410 return ERR_DSI_INVALID_INSTANCE;
\r
412 if (video_params->no_of_lanes > instance->max_lanes)
\r
414 return ERR_DSI_OUT_OF_BOUND;
\r
416 /* set up phy pll to required lane clock */
\r
417 err_code = mipi_dsih_phy_hs2lp_config(instance, video_params->max_hs_to_lp_cycles);
\r
418 err_code |= mipi_dsih_phy_lp2hs_config(instance, video_params->max_lp_to_hs_cycles);
\r
419 err_code = mipi_dsih_phy_clk_hs2lp_config(instance, video_params->max_clk_hs_to_lp_cycles);
\r
420 err_code |= mipi_dsih_phy_clk_lp2hs_config(instance, video_params->max_clk_lp_to_hs_cycles);
\r
421 video_params->non_continuous_clock = 0; // 1.21a new feature, set 1 result in half-bottom snow screen , disbale it
\r
422 mipi_dsih_non_continuous_clock(instance,video_params->non_continuous_clock);
\r
424 //err_code = mipi_dsih_dphy_configure(&(instance->phy_instance), video_params->no_of_lanes, video_params->byte_clock * 8);
\r
427 // return err_code;
\r
430 ratio_clock_xPF = (video_params->byte_clock * PRECISION_FACTOR) / (video_params->pixel_clock);
\r
431 video_size = video_params->h_active_pixels;
\r
432 /* set up ACKs and error reporting */
\r
433 mipi_dsih_hal_dpi_frame_ack_en(instance, video_params->receive_ack_packets);
\r
434 if (video_params->receive_ack_packets)
\r
435 { /* if ACK is requested, enable BTA, otherwise leave as is */
\r
436 mipi_dsih_hal_bta_en(instance, 1);
\r
438 /* mipi_dsih_hal_gen_cmd_mode_en(instance, 0); */
\r
439 mipi_dsih_hal_dpi_video_mode_en(instance, 1);
\r
440 /* get bytes per pixel and video size step (depending if loosely or not */
\r
441 switch (video_params->color_coding)
\r
443 case COLOR_CODE_16BIT_CONFIG1:
\r
444 case COLOR_CODE_16BIT_CONFIG2:
\r
445 case COLOR_CODE_16BIT_CONFIG3:
\r
446 bytes_per_pixel_x100 = 200;
\r
447 video_size_step = 1;
\r
449 case COLOR_CODE_18BIT_CONFIG1:
\r
450 case COLOR_CODE_18BIT_CONFIG2:
\r
451 mipi_dsih_hal_dpi_18_loosely_packet_en(instance, video_params->is_18_loosely);
\r
452 bytes_per_pixel_x100 = 225;
\r
453 if (!video_params->is_18_loosely)
\r
454 { /* 18bits per pixel and NOT loosely, packets should be multiples of 4 */
\r
455 video_size_step = 4;
\r
456 /* round up active H pixels to a multiple of 4 */
\r
457 for (; (video_size % 4) != 0; video_size++)
\r
464 video_size_step = 1;
\r
467 case COLOR_CODE_24BIT:
\r
468 bytes_per_pixel_x100 = 300;
\r
469 video_size_step = 1;
\r
471 case COLOR_CODE_20BIT_YCC422_LOOSELY:
\r
472 bytes_per_pixel_x100 = 250;
\r
473 video_size_step = 2;
\r
474 /* round up active H pixels to a multiple of 2 */
\r
475 if ((video_size % 2) != 0)
\r
480 case COLOR_CODE_24BIT_YCC422:
\r
481 bytes_per_pixel_x100 = 300;
\r
482 video_size_step = 2;
\r
483 /* round up active H pixels to a multiple of 2 */
\r
484 if ((video_size % 2) != 0)
\r
489 case COLOR_CODE_16BIT_YCC422:
\r
490 bytes_per_pixel_x100 = 200;
\r
491 video_size_step = 2;
\r
492 /* round up active H pixels to a multiple of 2 */
\r
493 if ((video_size % 2) != 0)
\r
498 case COLOR_CODE_30BIT:
\r
499 bytes_per_pixel_x100 = 375;
\r
500 video_size_step = 2;
\r
502 case COLOR_CODE_36BIT:
\r
503 bytes_per_pixel_x100 = 450;
\r
504 video_size_step = 2;
\r
506 case COLOR_CODE_12BIT_YCC420:
\r
507 bytes_per_pixel_x100 = 150;
\r
508 video_size_step = 2;
\r
509 /* round up active H pixels to a multiple of 2 */
\r
510 if ((video_size % 2) != 0)
\r
516 if (instance->log_error != 0)
\r
518 instance->log_error("sprdfb: invalid color coding");
\r
520 err_code = ERR_DSI_COLOR_CODING;
\r
523 if (err_code == OK)
\r
525 err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding);
\r
527 if (err_code != OK)
\r
531 mipi_dsih_hal_dpi_video_mode_type(instance, video_params->video_mode);
\r
532 mipi_dsih_hal_dpi_hline(instance, (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
533 mipi_dsih_hal_dpi_hbp(instance, ((video_params->h_back_porch_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
534 mipi_dsih_hal_dpi_hsa(instance, ((video_params->h_sync_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
535 mipi_dsih_hal_dpi_vactive(instance, video_params->v_active_lines);
\r
536 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
537 mipi_dsih_hal_dpi_vbp(instance, video_params->v_back_porch_lines);
\r
538 mipi_dsih_hal_dpi_vsync(instance, video_params->v_sync_lines);
\r
539 mipi_dsih_hal_dpi_hsync_pol(instance, !video_params->h_polarity);
\r
540 mipi_dsih_hal_dpi_vsync_pol(instance, !video_params->v_polarity);
\r
541 mipi_dsih_hal_dpi_dataen_pol(instance, !video_params->data_en_polarity);
\r
543 hs_timeout = ((video_params->h_total_pixels * video_params->v_active_lines) + (DSIH_PIXEL_TOLERANCE * bytes_per_pixel_x100) / 100);
\r
544 for (counter = 0x80; (counter < hs_timeout) && (counter > 2); counter--)
\r
546 if ((hs_timeout % counter) == 0)
\r
548 mipi_dsih_hal_timeout_clock_division(instance, counter);
\r
549 mipi_dsih_hal_lp_rx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
550 mipi_dsih_hal_hs_tx_timeout(instance, (uint16_t)(hs_timeout / counter));
\r
554 /* TX_ESC_CLOCK_DIV must be less than 20000KHz */
\r
555 mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessia
\r
556 /* video packetisation */
\r
557 if (video_params->video_mode == VIDEO_BURST_WITH_SYNC_PULSES)
\r
559 mipi_dsih_hal_dpi_null_packet_en(instance, 0);
\r
560 mipi_dsih_hal_dpi_multi_packet_en(instance, 0);
\r
561 err_code = mipi_dsih_hal_dpi_null_packet_size(instance, 0);
\r
562 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, 1);
\r
563 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
564 if (err_code != OK)
\r
568 /* BURST by default, returns to LP during ALL empty periods - energy saving */
\r
569 mipi_dsih_hal_dpi_lp_during_hfp(instance, 1);
\r
570 #if defined(CONFIG_FB_SCX35) && defined(CONFIG_FB_LCD_SSD2075_MIPI)
\r
571 mipi_dsih_hal_dpi_lp_during_hbp(instance, 0);//forbit return to lp during hbp
\r
573 mipi_dsih_hal_dpi_lp_during_hbp(instance, 1);
\r
575 mipi_dsih_hal_dpi_lp_during_vactive(instance, 1);
\r
576 mipi_dsih_hal_dpi_lp_during_vfp(instance, 1);
\r
577 mipi_dsih_hal_dpi_lp_during_vbp(instance, 1);
\r
578 mipi_dsih_hal_dpi_lp_during_vsync(instance, 1);
\r
581 if (instance->log_info != 0)
\r
583 instance->log_info("sprdfb: burst video");
\r
584 instance->log_info("sprdfb: h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
585 instance->log_info("sprdfb: video_size %ld", video_size);
\r
590 { /* non burst transmission */
\r
591 null_packet_size = 0;
\r
592 /* bytes to be sent - first as one chunk */
\r
593 bytes_per_chunk = (bytes_per_pixel_x100 * video_params->h_active_pixels) / 100 + VIDEO_PACKET_OVERHEAD;
\r
594 /* bytes being received through the DPI interface per byte clock cycle */
\r
595 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
596 /* check if the in pixels actually fit on the DSI link */
\r
597 if (total_bytes >= bytes_per_chunk)
\r
599 chunk_overhead = total_bytes - bytes_per_chunk;
\r
600 /* overhead higher than 1 -> enable multi packets */
\r
601 if (chunk_overhead > 1)
\r
602 { /* MULTI packets */
\r
603 for (video_size = video_size_step; video_size < video_params->h_active_pixels; video_size += video_size_step)
\r
604 { /* determine no of chunks */
\r
605 if ((((video_params->h_active_pixels * PRECISION_FACTOR) / video_size) % PRECISION_FACTOR) == 0)
\r
607 no_of_chunks = video_params->h_active_pixels / video_size;
\r
608 bytes_per_chunk = (bytes_per_pixel_x100 * video_size) / 100 + VIDEO_PACKET_OVERHEAD;
\r
609 if (total_bytes >= (bytes_per_chunk * no_of_chunks))
\r
611 bytes_left = total_bytes - (bytes_per_chunk * no_of_chunks);
\r
616 /* prevent overflow (unsigned - unsigned) */
\r
617 if (bytes_left > (NULL_PACKET_OVERHEAD * no_of_chunks))
\r
619 null_packet_size = (bytes_left - (NULL_PACKET_OVERHEAD * no_of_chunks)) / no_of_chunks;
\r
620 if (null_packet_size > MAX_NULL_SIZE)
\r
621 { /* avoid register overflow */
\r
622 null_packet_size = MAX_NULL_SIZE;
\r
627 { /* no multi packets */
\r
631 if (instance->log_info != 0)
\r
633 instance->log_info("sprdfb: no multi no null video");
\r
634 instance->log_info("sprdfb: h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR));
\r
635 instance->log_info("sprdfb: video_size %ld", video_size);
\r
637 /************************/
\r
639 /* video size must be a multiple of 4 when not 18 loosely */
\r
640 for (video_size = video_params->h_active_pixels; (video_size % video_size_step) != 0; video_size++)
\r
648 instance->log_error("sprdfb: resolution cannot be sent to display through current settings");
\r
649 err_code = ERR_DSI_OVERFLOW;
\r
652 err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, no_of_chunks);
\r
653 err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size);
\r
654 err_code = err_code? err_code: mipi_dsih_hal_dpi_null_packet_size(instance, null_packet_size);
\r
655 mipi_dsih_hal_dpi_null_packet_en(instance, null_packet_size > 0? 1: 0);
\r
656 mipi_dsih_hal_dpi_multi_packet_en(instance, (no_of_chunks > 1)? 1: 0);
\r
659 if (instance->log_info != 0)
\r
661 instance->log_info("sprdfb: total_bytes %d", total_bytes);
\r
662 instance->log_info("sprdfb: bytes_per_chunk %d", bytes_per_chunk);
\r
663 instance->log_info("sprdfb: bytes left %d", bytes_left);
\r
664 instance->log_info("sprdfb: null packets %d", null_packet_size);
\r
665 instance->log_info("sprdfb: chunks %ld", no_of_chunks);
\r
666 instance->log_info("sprdfb: video_size %ld", video_size);
\r
668 /************************/
\r
670 mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel);
\r
671 mipi_dsih_dphy_no_of_lanes(&(instance->phy_instance), video_params->no_of_lanes);
\r
672 /* enable high speed clock */
\r
673 //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
677 * Send a DCS write command
\r
678 * It sends the User Command Set commands listed in the DCS specification and
\r
679 * not the Manufacturer Command Set. To send the Manufacturer Commands use the
\r
680 * packet on the generic packets sending function
\r
681 * function sets the packet data type automatically
\r
682 * @param instance pointer to structure holding the DSI Host core information
\r
683 * @param vc destination virtual channel
\r
684 * @param params byte-addressed array of command parameters, including the
\r
686 * @param param_length length of the above array
\r
687 * @return error code
\r
688 * @note this function has an active delay to wait for the buffer to clear.
\r
689 * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time
\r
691 dsih_error_t mipi_dsih_dcs_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
693 uint8_t packet_type = 0;
\r
697 return ERR_DSI_OUT_OF_BOUND;
\r
700 if (param_length > 2)
\r
719 packet_type = 0x05; /* DCS short write no param */
\r
725 packet_type = 0x15; /* DCS short write 1 param */
\r
736 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
739 if (instance->log_error != 0)
\r
741 instance->log_error("invalid DCS command");
\r
743 return ERR_DSI_INVALID_COMMAND;
\r
746 switch(param_length)
\r
749 packet_type = 0x05; /* DCS short write no param */
\r
752 packet_type = 0x15; /* DCS short write 1 param */
\r
755 packet_type = 0x39; /* DCS long write/write_LUT command packet */
\r
759 return mipi_dsih_gen_wr_packet(instance, vc, packet_type, params, param_length);
\r
762 * Enable command mode
\r
763 * - This function shall be explicitly called before commands are send if they
\r
764 * are to be sent in command mode and not interlaced with video
\r
765 * - If video mode is ON, it will be turned off automatically
\r
766 * @param instance pointer to structure holding the DSI Host core information
\r
767 * @param en enable/disable
\r
769 void mipi_dsih_cmd_mode(dsih_ctrl_t * instance, int en)
\r
776 if (instance->status == INITIALIZED)
\r
778 mipi_dsih_hal_gen_cmd_mode_en(instance, en);
\r
781 if (instance->log_error != 0)
\r
783 instance->log_error("sprdfb: [mipi_dsih_cmd_mode] invalid instance");
\r
788 * Enable video mode
\r
789 * - If command mode is ON, it will be turned off automatically
\r
790 * @param instance pointer to structure holding the DSI Host core information
\r
791 * @param en enable/disable
\r
793 void mipi_dsih_video_mode(dsih_ctrl_t * instance, int en)
\r
800 if (instance->status == INITIALIZED)
\r
802 mipi_dsih_hal_dpi_video_mode_en(instance, en);
\r
805 if (instance->log_error != 0)
\r
807 instance->log_error("sprdfb: [mipi_dsih_video_mode] invalid instance");
\r
813 * Get the current active mode
\r
815 * - 2 DPI video mode
\r
817 int mipi_dsih_active_mode(dsih_ctrl_t * instance)
\r
819 if (mipi_dsih_hal_gen_is_cmd_mode(instance))
\r
823 else if (mipi_dsih_hal_dpi_is_video_mode(instance))
\r
830 * Send a generic write command
\r
831 * @param instance pointer to structure holding the DSI Host core information
\r
832 * @param vc destination virtual channel
\r
833 * @param params byte-addressed array of command parameters
\r
834 * @param param_length length of the above array
\r
835 * @return error code
\r
836 * @note this function has an active delay to wait for the buffer to clear.
\r
837 * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time
\r
839 dsih_error_t mipi_dsih_gen_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length)
\r
841 uint8_t data_type = 0;
\r
842 switch(param_length)
\r
857 return mipi_dsih_gen_wr_packet(instance, vc, data_type, params, param_length);
\r
860 * Send a packet on the generic interface
\r
861 * @param instance pointer to structure holding the DSI Host core information
\r
862 * @param vc destination virtual channel
\r
863 * @param data_type type of command, inserted in first byte of header
\r
864 * @param params byte array of command parameters
\r
865 * @param param_length length of the above array
\r
866 * @return error code
\r
867 * @note this function has an active delay to wait for the buffer to clear.
\r
868 * The delay is limited to:
\r
869 * (param_length / 4) x DSIH_FIFO_ACTIVE_WAIT x register access time
\r
870 * @note the controller restricts the sending of .
\r
871 * This function will not be able to send Null and Blanking packets due to
\r
872 * controller restriction
\r
874 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
876 dsih_error_t err_code = OK;
\r
877 /* active delay iterator */
\r
882 /* holds padding bytes needed */
\r
883 int compliment_counter = 0;
\r
884 uint8_t* payload = 0;
\r
885 /* temporary variable to arrange bytes into words */
\r
887 uint16_t word_count = 0;
\r
890 return ERR_DSI_INVALID_INSTANCE;
\r
892 if (instance->status != INITIALIZED)
\r
894 return ERR_DSI_INVALID_INSTANCE;
\r
896 if ((params == 0) && (param_length != 0)) /* pointer NULL */
\r
898 return ERR_DSI_OUT_OF_BOUND;
\r
900 if (param_length > 2)
\r
901 { /* long packet - write word count to header, and the rest to payload */
\r
902 payload = params + (2 * sizeof(params[0]));
\r
903 word_count = (params[1] << 8) | params[0];
\r
904 if ((param_length - 2) < word_count)
\r
906 if (instance->log_error != 0)
\r
908 instance->log_error("sprdfb: sent > input payload. complemented with zeroes");
\r
910 compliment_counter = (param_length - 2) - word_count;
\r
912 else if ((param_length - 2) > word_count)
\r
914 if (instance->log_error != 0)
\r
916 instance->log_error("sprdfb: Overflow - input > sent. payload truncated");
\r
919 for (i = 0; i < (param_length - 2); i += j)
\r
922 for (j = 0; (j < 4) && ((j + i) < (param_length - 2)); j++)
\r
923 { /* temp = (payload[i + 3] << 24) | (payload[i + 2] << 16) | (payload[i + 1] << 8) | payload[i]; */
\r
924 temp |= payload[i + j] << (j * 8);
\r
926 /* check if payload Tx fifo is not full */
\r
927 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
929 if (!mipi_dsih_hal_gen_packet_payload(instance, temp))
\r
934 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
936 return ERR_DSI_TIMEOUT;
\r
939 /* if word count entered by the user more than actual parameters received
\r
940 * fill with zeroes - a fail safe mechanism, otherwise controller will
\r
941 * want to send data from an empty buffer */
\r
942 for (i = 0; i < compliment_counter; i++)
\r
944 /* check if payload Tx fifo is not full */
\r
945 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
947 if (!mipi_dsih_hal_gen_packet_payload(instance, 0x00))
\r
952 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
954 return ERR_DSI_TIMEOUT;
\r
958 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
960 /* check if payload Tx fifo is not full */
\r
961 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
963 if (param_length == 0)
\r
965 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, 0x0);
\r
967 else if (param_length == 1)
\r
969 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, params[0]);
\r
973 err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, params[1], params[0]);
\r
978 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
980 err_code = ERR_DSI_TIMEOUT;
\r
985 * Send a DCS READ command to peripheral
\r
986 * function sets the packet data type automatically
\r
987 * @param instance pointer to structure holding the DSI Host core information
\r
988 * @param vc destination virtual channel
\r
989 * @param command DCS code
\r
990 * @param bytes_to_read no of bytes to read (expected to arrive at buffer)
\r
991 * @param read_buffer pointer to 8-bit array to hold the read buffer words
\r
992 * return read_buffer_length
\r
993 * @note this function has an active delay to wait for the buffer to clear.
\r
994 * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT
\r
995 * (waiting for command buffer, and waiting for receiving)
\r
996 * @note this function will enable BTA
\r
998 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
1000 if (instance == 0)
\r
1004 if (instance->status != INITIALIZED)
\r
1024 /* COMMAND_TYPE 0x06 - DCS Read no params refer to DSI spec p.47 */
\r
1025 return mipi_dsih_gen_rd_packet(instance, vc, 0x06, 0x0, command, bytes_to_read, read_buffer);
\r
1027 if (instance->log_error != 0)
\r
1029 instance->log_error("sprdfb: invalid DCS command");
\r
1036 * Send Generic READ command to peripheral
\r
1037 * - function sets the packet data type automatically
\r
1038 * @param instance pointer to structure holding the DSI Host core information
\r
1039 * @param vc destination virtual channel
\r
1040 * @param params byte array of command parameters
\r
1041 * @param param_length length of the above array
\r
1042 * @param bytes_to_read no of bytes to read (expected to arrive at buffer)
\r
1043 * @param read_buffer pointer to 8-bit array to hold the read buffer words
\r
1044 * return read_buffer_length
\r
1045 * @note this function has an active delay to wait for the buffer to clear.
\r
1046 * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT
\r
1047 * (waiting for command buffer, and waiting for receiving)
\r
1048 * @note this function will enable BTA
\r
1050 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
1052 uint8_t data_type = 0;
\r
1053 if (instance == 0)
\r
1057 if (instance->status != INITIALIZED)
\r
1061 switch(param_length)
\r
1065 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, 0x00, bytes_to_read, read_buffer);
\r
1068 return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, params[0], bytes_to_read, read_buffer);
\r
1071 return mipi_dsih_gen_rd_packet(instance, vc, data_type, params[1], params[0], bytes_to_read, read_buffer);
\r
1077 * Send READ packet to peripheral using the generic interface
\r
1078 * This will force command mode and stop video mode (because of BTA)
\r
1079 * @param instance pointer to structure holding the DSI Host core information
\r
1080 * @param vc destination virtual channel
\r
1081 * @param data_type generic command type
\r
1082 * @param lsb_byte first command parameter
\r
1083 * @param msb_byte second command parameter
\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_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
1094 dsih_error_t err_code = OK;
\r
1098 int last_count = 0;
\r
1099 uint32_t temp[1] = {0};
\r
1100 if (instance == 0)
\r
1104 if (instance->status != INITIALIZED)
\r
1108 if (bytes_to_read < 1)
\r
1112 if (read_buffer == 0)
\r
1116 #ifndef FB_CHECK_ESD_IN_VFP
\r
1117 /* make sure command mode is on */
\r
1118 mipi_dsih_cmd_mode(instance, 1);
\r
1120 /* make sure receiving is enabled */
\r
1121 mipi_dsih_hal_bta_en(instance, 1);
\r
1122 /* listen to the same virtual channel as the one sent to */
\r
1123 mipi_dsih_hal_gen_rd_vc(instance, vc);
\r
1124 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
1125 { /* check if payload Tx fifo is not full */
\r
1126 if (!mipi_dsih_hal_gen_cmd_fifo_full(instance))
\r
1128 mipi_dsih_hal_gen_packet_header(instance, vc, data_type, msb_byte, lsb_byte);
\r
1132 if (!(timeout < DSIH_FIFO_ACTIVE_WAIT))
\r
1134 if (instance->log_error != 0)
\r
1136 instance->log_error("sprdfb: tx rd command timed out");
\r
1140 /* loop for the number of words to be read */
\r
1141 for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++)
\r
1142 { /* check if command transaction is done */
\r
1143 if (!mipi_dsih_hal_gen_rd_cmd_busy(instance))
\r
1145 if (!mipi_dsih_hal_gen_read_fifo_empty(instance))
\r
1147 for (counter = 0; (!mipi_dsih_hal_gen_read_fifo_empty(instance)); counter += 4)
\r
1149 err_code = mipi_dsih_hal_gen_read_payload(instance, temp);
\r
1154 if (counter < bytes_to_read)
\r
1156 for (i = 0; i < 4; i++)
\r
1158 if ((counter + i) < bytes_to_read)
\r
1160 /* put 32 bit temp in 4 bytes of buffer passed by user*/
\r
1161 read_buffer[counter + i] = (uint8_t)(temp[0] >> (i * 8));
\r
1162 last_count = i + counter;
\r
1166 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
1168 last_count = i + counter;
\r
1175 last_count = counter;
\r
1176 for (i = 0; i < 4; i++)
\r
1178 if ((uint8_t)(temp[0] >> (i * 8)) != 0x00)
\r
1180 last_count = i + counter;
\r
1185 return last_count + 1;
\r
1187 #ifdef FB_CHECK_ESD_IN_VFP
\r
1188 else if(timeout == (DSIH_FIFO_ACTIVE_WAIT - 1))//else
\r
1193 if (instance->log_error != 0)
\r
1195 instance->log_error("sprdfb: rx buffer empty");
\r
1200 #ifdef FB_CHECK_ESD_IN_VFP
\r
1204 if (instance->log_error != 0)
\r
1206 instance->log_error("sprdfb: rx command timed out");
\r
1211 * Dump values stored in the DSI host core registers
\r
1212 * @param instance pointer to structure holding the DSI Host core information
\r
1213 * @param all whether to dump all the registers, no register_config array need
\r
1214 * be provided if dump is to standard IO
\r
1215 * @param config array of register_config_t type where addresses and values are
\r
1217 * @param config_length the length of the config array
\r
1218 * @return the number of the registers that were read
\r
1220 uint32_t mipi_dsih_dump_register_configuration(dsih_ctrl_t * instance, int all, register_config_t *config, uint16_t config_length)
\r
1222 uint32_t current0 = 0;
\r
1223 uint16_t count = 0;
\r
1224 if (instance == 0)
\r
1226 return ERR_DSI_INVALID_INSTANCE;
\r
1228 if (instance->status != INITIALIZED)
\r
1230 return ERR_DSI_INVALID_INSTANCE;
\r
1233 { /* dump all registers */
\r
1234 for (current0 = R_DSI_HOST_VERSION; current0 <= R_DSI_HOST_PHY_TMR_LPCLK_CFG; count++, current0 += (R_DSI_HOST_PWR_UP - R_DSI_HOST_VERSION))
\r
1236 if ((config_length == 0) || (config == 0) || count >= config_length)
\r
1237 { /* no place to write - write to STD IO */
\r
1238 if (instance->log_info != 0)
\r
1240 instance->log_info("sprdfb: DSI 0x%lX:0x%lX", current0, mipi_dsih_read_word(instance, current0));
\r
1245 config[count].addr = current0;
\r
1246 config[count].data = mipi_dsih_read_word(instance, current0);
\r
1254 if (instance->log_error != 0)
\r
1256 instance->log_error("sprdfb: invalid buffer");
\r
1261 for (count = 0; count < config_length; count++)
\r
1263 config[count].data = mipi_dsih_read_word(instance, config[count].addr);
\r
1270 * Write values to DSI host core registers
\r
1271 * @param instance pointer to structure holding the DSI Host core information
\r
1272 * @param config array of register_config_t type where register addresses and
\r
1273 * their new values are stored
\r
1274 * @param config_length the length of the config array
\r
1275 * @return the number of the registers that were written to
\r
1277 uint32_t mipi_dsih_write_register_configuration(dsih_ctrl_t * instance, register_config_t *config, uint16_t config_length)
\r
1279 uint16_t count = 0;
\r
1280 if (instance == 0)
\r
1282 return ERR_DSI_INVALID_INSTANCE;
\r
1284 if (instance->status != INITIALIZED)
\r
1286 return ERR_DSI_INVALID_INSTANCE;
\r
1288 for (count = 0; count < config_length; count++)
\r
1290 mipi_dsih_write_word(instance, config[count].addr, config[count].data);
\r
1295 * Register a handler for a specific event
\r
1296 * - The handler will be called when this specific event occurs
\r
1297 * @param instance pointer to structure holding the DSI Host core information
\r
1298 * @param event enum
\r
1299 * @param handler call back to handler function to handle the event
\r
1300 * @return error code
\r
1302 dsih_error_t mipi_dsih_register_event(dsih_ctrl_t * instance, dsih_event_t event, void (*handler)(dsih_ctrl_t *, void *))
\r
1304 uint32_t mask = 1;
\r
1305 uint32_t temp = 0;
\r
1306 if (event >= DSI_MAX_EVENT)
\r
1308 return ERR_DSI_INVALID_EVENT;
\r
1312 return ERR_DSI_INVALID_HANDLE;
\r
1314 if (instance == 0)
\r
1316 return ERR_DSI_INVALID_INSTANCE;
\r
1318 if (instance->status != INITIALIZED)
\r
1320 return ERR_DSI_INVALID_INSTANCE;
\r
1322 instance->event_registry[event] = handler;
\r
1323 if (event < HS_CONTENTION)
\r
1325 temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff);
\r
1326 temp &= ~(mask << event);
\r
1327 temp |= (0 & mask) << event;
\r
1328 mipi_dsih_hal_int_mask_0(instance, temp);
\r
1332 temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff);
\r
1333 temp &= ~(mask << (event - HS_CONTENTION));
\r
1334 temp |= (0 & mask) << (event - HS_CONTENTION);
\r
1335 mipi_dsih_hal_int_mask_1(instance, temp);
\r
1336 if (event == RX_CRC_ERR)
\r
1337 { /* automatically enable CRC reporting */
\r
1338 mipi_dsih_hal_gen_crc_rx_en(instance, 1);
\r
1344 * Clear an already registered event
\r
1345 * - Callback of the handler will be removed
\r
1346 * @param instance pointer to structure holding the DSI Host core information
\r
1347 * @param event enum
\r
1348 * @return error code
\r
1350 dsih_error_t mipi_dsih_unregister_event(dsih_ctrl_t * instance, dsih_event_t event)
\r
1352 uint32_t mask = 1;
\r
1353 uint32_t temp = 0;
\r
1354 if (event >= DSI_MAX_EVENT)
\r
1356 return ERR_DSI_INVALID_EVENT;
\r
1358 if (instance == 0)
\r
1360 return ERR_DSI_INVALID_INSTANCE;
\r
1362 if (instance->status != INITIALIZED)
\r
1364 return ERR_DSI_INVALID_INSTANCE;
\r
1366 instance->event_registry[event] = 0;
\r
1367 if (event < HS_CONTENTION)
\r
1369 temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff);
\r
1370 temp &= ~(mask << event);
\r
1371 temp |= (1 & mask) << event;
\r
1372 mipi_dsih_hal_int_mask_0(instance, temp);
\r
1376 temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff);
\r
1377 temp &= ~(mask << (event - HS_CONTENTION));
\r
1378 temp |= (1 & mask) << (event - HS_CONTENTION);
\r
1379 mipi_dsih_hal_int_mask_1(instance, temp);
\r
1380 if (event == RX_CRC_ERR)
\r
1381 { /* automatically disable CRC reporting */
\r
1382 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1388 * Clear all registered events at once
\r
1389 * @param instance pointer to structure holding the DSI Host core information
\r
1390 * @return error code
\r
1392 dsih_error_t mipi_dsih_unregister_all_events(dsih_ctrl_t * instance)
\r
1395 if (instance == 0)
\r
1397 return ERR_DSI_INVALID_INSTANCE;
\r
1399 if (instance->status != INITIALIZED)
\r
1401 return ERR_DSI_INVALID_INSTANCE;
\r
1403 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1405 instance->event_registry[i] = 0;
\r
1407 mipi_dsih_hal_int_mask_0(instance, 0xffffff);
\r
1408 mipi_dsih_hal_int_mask_1(instance, 0xffffff);
\r
1409 /* automatically disable CRC reporting */
\r
1410 mipi_dsih_hal_gen_crc_rx_en(instance, 0);
\r
1414 * This event handler shall be called upon receiving any event
\r
1415 * it will call the specific callback (handler) registered for the invoking
\r
1416 * event. Registration is done beforehand using mipi_dsih_register_event
\r
1417 * its signature is void * so it could be OS agnostic (for it to be
\r
1418 * registered in any OS/Interrupt controller)
\r
1419 * @param param pointer to structure holding the DSI Host core information
\r
1420 * @note This function must be registered with the DSI IRQs
\r
1422 void mipi_dsih_event_handler(void * param)
\r
1424 dsih_ctrl_t * instance = (dsih_ctrl_t *)(param);
\r
1426 uint32_t status_0;
\r
1427 uint32_t status_1;
\r
1429 if (instance == 0)
\r
1434 status_0 = mipi_dsih_hal_int_status_0(instance, 0xffffffff);
\r
1435 status_1 = mipi_dsih_hal_int_status_1(instance, 0xffffffff);
\r
1437 for (i = 0; i < DSI_MAX_EVENT; i++)
\r
1439 if (instance->event_registry[i] != 0)
\r
1441 if (i < HS_CONTENTION)
\r
1443 if ((status_0 & (1 << i)) != 0)
\r
1445 instance->event_registry[i](instance, &i);
\r
1450 if ((status_1 & (1 << (i - HS_CONTENTION))) != 0)
\r
1452 instance->event_registry[i](instance, &i);
\r
1459 * Reset the DSI Host controller
\r
1460 * - Sends a pulse to the shut down register
\r
1461 * @param instance pointer to structure holding the DSI Host core information
\r
1463 void mipi_dsih_reset_controller(dsih_ctrl_t * instance)
\r
1465 mipi_dsih_hal_power(instance, 0);
\r
1466 mipi_dsih_hal_power(instance, 1);
\r
1469 * Shut down the DSI Host controller
\r
1470 * @param instance pointer to structure holding the DSI Host core information
\r
1471 * @param shutdown (1) power up (0)
\r
1473 void mipi_dsih_shutdown_controller(dsih_ctrl_t * instance, int shutdown)
\r
1475 mipi_dsih_hal_power(instance, !shutdown);
\r
1478 * Reset the PHY module being controlled by the DSI Host controller
\r
1479 * - Sends a pulse to the PPI reset signal
\r
1480 * @param instance pointer to structure holding the DSI Host core information
\r
1482 void mipi_dsih_reset_phy(dsih_ctrl_t * instance)
\r
1484 mipi_dsih_dphy_reset(&(instance->phy_instance), 0);
\r
1485 mipi_dsih_dphy_reset(&(instance->phy_instance), 1);
\r
1488 * Shut down the PHY module being controlled by the DSI Host controller
\r
1489 * @param instance pointer to structure holding the DSI Host core information
\r
1490 * @param shutdown (1) power up (0)
\r
1492 void mipi_dsih_shutdown_phy(dsih_ctrl_t * instance, int shutdown)
\r
1494 mipi_dsih_dphy_shutdown(&(instance->phy_instance), !shutdown);
\r
1498 sprd Aoke added for power saving while suspend
\r
1500 void mipi_dsih_ulps_mode(dsih_ctrl_t * instance, int en)
\r
1502 mipi_dsih_dphy_ulps_data_lanes(&(instance->phy_instance),en);
\r
1503 mipi_dsih_dphy_ulps_clk_lane(&(instance->phy_instance),en);
\r
1506 * Configure the eDPI interface
\r
1507 * - Programs the controller to receive pixels on the DPI interface and send them
\r
1508 * as commands (write memory start and write memory continue) instead of a
\r
1510 * @param instance pointer to structure holding the DSI Host core information
\r
1511 * @param video_params pointer to the command mode video parameters context
\r
1512 * @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
1513 * @return error code
\r
1515 dsih_error_t mipi_dsih_edpi_video(dsih_ctrl_t * instance, dsih_cmd_mode_video_t *video_params, int send_setup_packets)
\r
1517 dsih_error_t err_code = OK;
\r
1518 uint8_t buf[7] = {0};
\r
1519 uint32_t bytes_per_pixel_x100 = 0;
\r
1520 mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel);
\r
1521 mipi_dsih_cmd_mode(instance, 1);
\r
1522 err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding);
\r
1523 /* define whether write memory commands will be sent in LP or HS */
\r
1524 err_code = err_code? err_code: mipi_dsih_hal_dcs_wr_tx_type(instance, 3, video_params->lp); /* long packet*/
\r
1525 if (send_setup_packets)
\r
1527 /* define pixel packing format - 1 param */
\r
1529 /* colour depth: table 6 DCS spec. 3:1| 8:2| 12:3| 16:5| 18:6| 24:7*/
\r
1530 switch (video_params->color_coding)
\r
1545 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 2);
\r
1548 instance->log_error("sprdfb: error setting up command video - colour depth");
\r
1550 /* set column address (left to right) - 4 param */
\r
1551 buf[0] = 0x05; /* cmd length */
\r
1553 buf[2] = 0x2A; /* cmd opcode */
\r
1554 buf[3] = (uint8_t)(video_params->h_start >> 8); /* payload start */
\r
1555 buf[4] = (uint8_t)(video_params->h_start);
\r
1556 buf[5] = (uint8_t)(video_params->h_active_pixels >> 8);
\r
1557 buf[6] = (uint8_t)(video_params->h_active_pixels);
\r
1558 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7);
\r
1561 instance->log_error("sprdfb: error setting up command video - set column address");
\r
1563 /* set page address (top to bottom) 4 - param*/
\r
1564 buf[0] = 0x05; /* cmd length */
\r
1566 buf[2] = 0x2B; /* cmd opcode */
\r
1567 buf[3] = (uint8_t)(video_params->v_start >> 8); /* payload start */
\r
1568 buf[4] = (uint8_t)(video_params->v_start);
\r
1569 buf[5] = (uint8_t)(video_params->v_active_lines >> 8);
\r
1570 buf[6] = (uint8_t)(video_params->v_active_lines);
\r
1571 err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7);
\r
1574 instance->log_error("sprdfb: error setting up command video - set page address");
\r
1577 switch (video_params->color_coding)
\r
1579 case COLOR_CODE_16BIT_CONFIG1:
\r
1580 case COLOR_CODE_16BIT_CONFIG2:
\r
1581 case COLOR_CODE_16BIT_CONFIG3:
\r
1582 bytes_per_pixel_x100 = 200;
\r
1584 case COLOR_CODE_18BIT_CONFIG1:
\r
1585 case COLOR_CODE_18BIT_CONFIG2:
\r
1586 bytes_per_pixel_x100 = 225;
\r
1588 case COLOR_CODE_24BIT:
\r
1589 bytes_per_pixel_x100 = 300;
\r
1591 case COLOR_CODE_20BIT_YCC422_LOOSELY:
\r
1592 bytes_per_pixel_x100 = 250;
\r
1594 case COLOR_CODE_24BIT_YCC422:
\r
1595 bytes_per_pixel_x100 = 300;
\r
1597 case COLOR_CODE_16BIT_YCC422:
\r
1598 bytes_per_pixel_x100 = 200;
\r
1600 case COLOR_CODE_30BIT:
\r
1601 bytes_per_pixel_x100 = 375;
\r
1603 case COLOR_CODE_36BIT:
\r
1604 bytes_per_pixel_x100 = 450;
\r
1606 case COLOR_CODE_12BIT_YCC420:
\r
1607 bytes_per_pixel_x100 = 150;
\r
1610 if (instance->log_error != 0)
\r
1612 instance->log_error("sprdfb: invalid color coding");
\r
1614 err_code = ERR_DSI_COLOR_CODING;
\r
1617 if (video_params->te)
\r
1619 mipi_dsih_hal_bta_en(instance, video_params->te);
\r
1620 /* enable tearing effect */
\r
1621 mipi_dsih_tear_effect_ack(instance, video_params->te);
\r
1623 err_code = mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 1);
\r
1625 mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1);
\r
1626 if ((((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100) > video_params->h_active_pixels)
\r
1628 mipi_dsih_hal_edpi_max_allowed_size(instance, video_params->h_active_pixels);
\r
1632 mipi_dsih_hal_edpi_max_allowed_size(instance, (((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100));
\r
1637 /* PRESP Time outs */
\r
1639 * Timeout for peripheral (for controller to stay still) after LP data
\r
1640 * transmission write requests
\r
1641 * @param instance pointer to structure holding the DSI Host core information
\r
1642 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1643 * link still, after sending a low power write operation. This period is
\r
1644 * measured in cycles of lanebyteclk
\r
1646 void mipi_dsih_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1648 mipi_dsih_hal_presp_timeout_low_power_write(instance, no_of_byte_cycles);
\r
1651 * Timeout for peripheral (for controller to stay still) after LP data
\r
1652 * transmission read requests
\r
1653 * @param instance pointer to structure holding the DSI Host core information
\r
1654 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1655 * link still, after sending a low power read operation. This period is
\r
1656 * measured in cycles of lanebyteclk
\r
1658 void mipi_dsih_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1660 mipi_dsih_hal_presp_timeout_low_power_read(instance, no_of_byte_cycles);
\r
1663 * Timeout for peripheral (for controller to stay still) after HS data
\r
1664 * transmission write requests
\r
1665 * @param instance pointer to structure holding the DSI Host core information
\r
1666 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1667 * link still, after sending a high-speed write operation. This period is
\r
1668 * measured in cycles of lanebyteclk
\r
1670 void mipi_dsih_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1672 mipi_dsih_hal_presp_timeout_high_speed_write(instance, no_of_byte_cycles);
\r
1675 * Timeout for peripheral between HS data transmission read requests
\r
1676 * @param instance pointer to structure holding the DSI Host core information
\r
1677 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1678 * link still, after sending a high-speed read operation. This period is
\r
1679 * measured in cycles of lanebyteclk
\r
1681 void mipi_dsih_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1683 mipi_dsih_hal_presp_timeout_high_speed_read(instance, no_of_byte_cycles);
\r
1686 * Timeout for peripheral (for controller to stay still) after bus turn around
\r
1687 * @param instance pointer to structure holding the DSI Host core information
\r
1688 * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the
\r
1689 * link still, after sending a BTA operation. This period is
\r
1690 * measured in cycles of lanebyteclk
\r
1692 void mipi_dsih_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles)
\r
1694 mipi_dsih_hal_presp_timeout_bta(instance, no_of_byte_cycles);
\r
1696 uint16_t mipi_dsih_check_dbi_fifos_state(dsih_ctrl_t * instance)
\r
1699 while( cnt < 5000 && mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15)
\r
1703 return (mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15) ? -1 : 1;
\r
1705 uint16_t mipi_dsih_check_ulpm_mode(dsih_ctrl_t * instance)
\r
1707 return (mipi_dsih_read_word(instance, R_DSI_HOST_PHY_STATUS) != 0x1528) ? -1 : 1;
\r