2 *-----------------------------------------------------------------------------
3 * Filename: sdvo_hdmi.c
5 *-----------------------------------------------------------------------------
6 * Copyright (c) 2002-2010, Intel Corporation.
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 *-----------------------------------------------------------------------------
28 * Port driver HDMI interface functions
29 *-----------------------------------------------------------------------------
32 #include "sdvo_hdmi.h"
36 Currently if omitting out this attributes as this should NOT be avalable
38 TODO: Integrate this attributes into HDMI */
40 #define PD_HDMI_COLORIMETRY_256_RGB 0
41 #define PD_HDMI_COLORIMETRY_220_RGB 1
42 #define PD_HDMI_COLORIMETRY_422_YCRCB 2
43 #define PD_HDMI_COLORIMETRY_444_YCRCB 3
45 #define PD_HDMI_PIXEL_REPLICATION_1X_REPITION 1
46 #define PD_HDMI_PIXEL_REPLICATION_2X_REPITION 2
47 #define PD_HDMI_PIXEL_REPLICATION_4X_REPITION 4
48 /-----------------------------------------------------------------------------/
49 {PD_ATTR_ID_COLORIMETRY, MAKE_NAME("Colorimetry"), {4}, {0x0F},
50 GET_CURRENT_COLORIMETRY, SET_CURRENT_COLORIMETRY},
52 /* 256 RGB is passthrough, real value is 0x01 but 0x00 works as well
53 and upon boot up the value is 0x00 */
54 {PD_HDMI_COLORIMETRY_256_RGB,
55 MAKE_NAME("RGB 256 level"), {0}, {0x00}, 0, 0},
56 {PD_HDMI_COLORIMETRY_220_RGB,
57 MAKE_NAME("RGB 220 level"), {0}, {0x02}, 0, 0},
58 {PD_HDMI_COLORIMETRY_422_YCRCB,
59 MAKE_NAME("4:2:2 YcrCb"), {0}, {0x04}, 0, 0},
60 {PD_HDMI_COLORIMETRY_444_YCRCB,
61 MAKE_NAME("4:4:4 YcrCb"), {0}, {0x08}, 0, 0},
63 {PD_ATTR_ID_PIXEL_REPLICATION, MAKE_NAME("Pixel Replication"), {3}, {0x1F},
64 GET_PIXEL_REPLICATION, SET_PIXEL_REPLICATION},
66 {PD_HDMI_PIXEL_REPLICATION_1X_REPITION,
67 MAKE_NAME("No Repetition"), {0}, {0x00}, 0, 0},
68 {PD_HDMI_PIXEL_REPLICATION_2X_REPITION,
69 MAKE_NAME("1X Repetition"), {0}, {0x01}, 0, 0},
70 {PD_HDMI_PIXEL_REPLICATION_4X_REPITION,
71 MAKE_NAME("3X Repetition"), {0}, {0x03}, 0, 0},
73 #if defined(SDVO_HDMI)
75 /* ============================================================================
76 Function : sdvo_hdmi_transmitter
80 Remarks : Detect if transmitter is a HDMI transmitter.
83 ------------------------------------------------------------------------- */
84 sdvo_status_t sdvo_hdmi_transmitter(sdvo_device_context_t *p_ctx)
86 return sdvo_get_supported_encoding_modes(p_ctx,&(p_ctx->hdmi.version));
89 /* ============================================================================
90 Function : sdvo_hdmi_support is called to see if the transmitter
91 and the monitor device support HDMI.
93 Parameters : p_context: Pointer to port driver allocated context
98 Returns : sdvo_status_t : Status of command execution
99 ------------------------------------------------------------------------- */
100 sdvo_status_t sdvo_hdmi_support(void *p_context)
102 sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
103 sdvo_status_t status = SS_SUCCESS;
105 /* Monitor support is determined by valid CEA 861 extension and */
106 /* vendor block with 0xC03 IEEE regstration ID */
108 if((p_ctx->p_callback->eld) == NULL){
109 return SS_NOT_SUPPORTED;
112 if((*p_ctx->p_callback->eld)->vendor_block_size) {
113 return SS_NOT_SUPPORTED;
116 if((*p_ctx->p_callback->eld)->vendor_ieee_id != CEA_IEEE_HDMI_ID) {
117 return SS_NOT_SUPPORTED;
120 /* Transmitter support is determined by SDVO GetSupportDigitalEncodingModes */
121 status = sdvo_hdmi_transmitter(p_ctx);
122 if (status != SS_SUCCESS) {
131 /* ============================================================================
132 Function : sdvo_hdmi_audio_characteristic
136 Remarks : Set audio characteristic to be used in ELD calcilation.
137 TODO: Make sure this is recalled if hotplug is detected
140 ------------------------------------------------------------------------- */
141 sdvo_status_t sdvo_hdmi_audio_characteristic(sdvo_device_context_t *p_ctx)
143 sdvo_status_t status;
144 i2c_reg_t hdmi_audio_char[3];
146 /* Skip since no CEA data available */
147 if((!p_ctx->p_callback) || ((p_ctx->p_callback->eld) == NULL)){
148 return SS_NOT_SUPPORTED;
150 if(*(p_ctx->p_callback->eld) == NULL){
151 return SS_NOT_SUPPORTED;
154 status = sdvo_get_hdmi_audio_transmission_char(p_ctx, hdmi_audio_char);
155 if(status == SS_SUCCESS){
156 (*p_ctx->p_callback->eld)->audio_flag |= PD_AUDIO_CHAR_AVAIL;
157 (*p_ctx->p_callback->eld)->NPL = hdmi_audio_char[0];
158 (*p_ctx->p_callback->eld)->K0 = hdmi_audio_char[1];
159 (*p_ctx->p_callback->eld)->K1 = hdmi_audio_char[2];
161 (*p_ctx->p_callback->eld)->audio_flag &= ~PD_AUDIO_CHAR_AVAIL;
167 /* ============================================================================
168 Function : sdvo_hdmi_configure is called to program AVI infoframes, SPD
169 infoframes, ELD data for audio, colorimetry and pixel replication.
171 Parameters : p_context: Pointer to port driver allocated context
173 p_mode: Point to current video output display mode
177 Returns : sdvo_status_t : Status of command execution
178 ------------------------------------------------------------------------- */
179 sdvo_status_t sdvo_hdmi_configure(sdvo_device_context_t *p_ctx)
182 sdvo_status_t status = SS_SUCCESS;
183 i2c_reg_t encoding_mode = DVI_MODE;
185 if((p_ctx->p_callback->eld) == NULL){
186 sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
187 return SS_NOT_SUPPORTED;
189 if(*(p_ctx->p_callback->eld) == NULL){
190 sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
191 return SS_NOT_SUPPORTED;
194 /* Prepare buffer for video information. Video only requires a total of 3
195 * buffers. (0)ELD (1)AVI (2)SPD. SO we will set it to 2 indexbased buffer */
196 status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
200 status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
204 /* Send pixel replication and colorimetry */
205 if (sdvo_hdmi_pr_and_color(p_ctx) != SS_SUCCESS) {
206 PD_ERROR("Fail toset pixel replication and colorimetry");
209 /* Build and send ELD Info Frames */
210 if(sdvo_hdmi_send_eld(p_ctx) != SS_SUCCESS){
211 PD_ERROR("Fail to write ELD to transmitter");
214 /* Build and send AVI Info Frames */
215 if (sdvo_hdmi_avi_info_frame(p_ctx) != SS_SUCCESS) {
216 PD_ERROR("Fail to write AVI infoframes to transmitter");
219 /* Build and send SPD Info Frames */
221 if (sdvo_hdmi_spd_info_frame(p_ctx) != SS_SUCCESS) {
222 PD_ERROR("Fail to write SPD Infoframes to transmitter");
225 /* Set to HDMI mode */
226 if((*p_ctx->p_callback->eld)->audio_support){
227 encoding_mode = HDMI_MODE;
229 status = sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
230 if (status != SS_SUCCESS) {
231 PD_DEBUG("sdvo: Fail to set HDMI mode ");
236 /* ============================================================================
237 Function : sdvo_hdmi_pr_and_color is called to send pixel replication
238 and colorimetry data to SDVO device.
240 Parameters : p_context: Pointer to port driver allocated context
245 Returns : sdvo_status_t : Status of command execution
246 ------------------------------------------------------------------------- */
247 sdvo_status_t sdvo_hdmi_pr_and_color(sdvo_device_context_t *p_context)
249 sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
250 sdvo_status_t status = SS_SUCCESS;
251 i2c_reg_t pixel_rep = (i2c_reg_t)(*p_ctx->p_callback->eld)->pixel_rep - 1;
252 i2c_reg_t quantization = (i2c_reg_t)(*p_ctx->p_callback->eld)->quantization;
254 /* Set pixel replication */
255 status = sdvo_execute_command(p_ctx, SET_PIXEL_REPLICATION,
258 if (status != SS_SUCCESS) {
262 /* Set colorimetry */
263 status = sdvo_execute_command(p_ctx, SET_CURRENT_COLORIMETRY,
266 if (status != SS_SUCCESS) {
271 /* ============================================================================
272 Function : sdvo_hdmi_send_eld
276 Remarks : Builds eld structure and write it into SDVO ELD buffers
279 ------------------------------------------------------------------------- */
280 sdvo_status_t sdvo_hdmi_send_eld(sdvo_device_context_t *p_ctx)
282 sdvo_status_t status;
283 sdvo_audio_state_t audio_state;
285 if((p_ctx->p_callback->eld) == NULL){
286 return SS_NOT_SUPPORTED;
288 if(*(p_ctx->p_callback->eld) == NULL){
289 return SS_NOT_SUPPORTED;
291 if(!((*p_ctx->p_callback->eld)->audio_flag & ELD_AVAIL)){
292 PD_DEBUG("Eld not available");
293 return SS_NOT_SUPPORTED;
296 /* ELD 1.0, CEA version retrieve from callback */
297 (*p_ctx->p_callback->eld)->cea_ver = 0;
298 (*p_ctx->p_callback->eld)->eld_ver = 1;
300 /* Capability Flags */
301 (*p_ctx->p_callback->eld)->repeater = 0;
302 (*p_ctx->p_callback->eld)->hdcp = 0;
304 (*p_ctx->p_callback->eld)->_44ms = 0;
307 /* We do not provide Monitor length */
308 (*p_ctx->p_callback->eld)->mnl = 0;
311 (*p_ctx->p_callback->eld)->sadc = 0;
314 audio_state.value = 0;
315 audio_state.eld_valid = FALSE;
316 audio_state.presense_detect = TRUE;
317 status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
318 1, (i2c_reg_t *)&audio_state,
320 if (status != SS_SUCCESS) {
321 PD_ERROR("Set Audio eld_valid fail (FALSE)");
325 /* Write ELD to SDVO buffers */
326 status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_ELD_BUFFER ,
327 0, (*p_ctx->p_callback->eld)->eld_ptr, SDVO_HDMI_ELD_BUFFER_SIZE);
328 if (status != SS_SUCCESS) {
329 PD_ERROR("Write ELD Failed !");
333 /* Send audio state change by toggling eld_valid bit */
334 audio_state.eld_valid = TRUE;
335 status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
336 1, (i2c_reg_t *)&audio_state,
338 if (status != SS_SUCCESS) {
339 PD_ERROR("Set Audio eld_valid fail (TRUE)");
345 /* ============================================================================
346 Function : sdvo_hdmi_avi_info_frame is called to program AVI infoframes
348 Parameters : p_context: Pointer to port driver allocated context
350 p_mode: Point to current video output display mode
354 Returns : sdvo_status_t : Status of command execution
355 ------------------------------------------------------------------------- */
356 sdvo_status_t sdvo_hdmi_avi_info_frame(sdvo_device_context_t *p_context)
358 sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
359 sdvo_status_t status = SS_SUCCESS;
360 unsigned long sum = 0;
364 /* Initialize AVI InfoFrame to no scan info, no bar info, no active format */
365 /* mode rgb, active format same as picture format */
366 /* no aspect ratio, no colorimetry, no scaling */
367 pd_memset(&avi, 0, sizeof(sdvo_avi_info_t));
368 avi.header.type = SDVO_HDMI_AVI_INFO_TYPE;
369 avi.header.version = 2;
370 avi.header.length = SDVO_HDMI_AVI_BUFFER_SIZE - sizeof(sdvo_info_header_t);
372 /* Fill in VIC, colorimetry, aspect ratio */
374 /* Set Video ID Code */
375 avi.video_id_code = (unsigned char)(*p_ctx->p_callback->eld)->video_code;
377 /* Set aspect ratio */
378 avi.pic_aspect_ratio = (unsigned char)(*p_ctx->p_callback->eld)->aspect_ratio;
380 /* Set Colorimetry */
381 avi.colorimetry = (unsigned char)(*p_ctx->p_callback->eld)->colorimetry;
384 for (i= 0; i < SDVO_HDMI_AVI_BUFFER_SIZE; i++) {
387 avi.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
389 /* Send data to SDVO device */
390 status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_AVI_BUFFER, 0, avi.data,
391 SDVO_HDMI_AVI_BUFFER_SIZE);
394 /* ============================================================================
395 Function : sdvo_hdmi_spd_info_frame is called to program SPD infoframes
397 Parameters : p_context: Pointer to port driver allocated context
402 Returns : sdvo_status_t : Status of command execution
403 ------------------------------------------------------------------------- */
404 sdvo_status_t sdvo_hdmi_spd_info_frame(sdvo_device_context_t *p_context)
406 sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
407 sdvo_status_t status = SS_SUCCESS;
409 unsigned long sum = 0;
412 /* Initialize SPD InfoFrame to zero */
413 pd_memset(&spd, 0, sizeof(sdvo_spd_info_t));
414 spd.header.type = SDVO_HDMI_SPD_INFO_TYPE;
415 spd.header.version = 1;
416 spd.header.length = SDVO_HDMI_SPD_BUFFER_SIZE - sizeof(sdvo_info_header_t);
418 pd_memcpy(spd.vendor_name, SDVO_HDMI_VENDOR_NAME, SDVO_HDMI_INTEL_VENDOR_NAME_SIZE);
419 pd_memcpy(spd.product_desc,
420 SDVO_HDMI_VENDOR_DESCRIPTION, SDVO_HDMI_IEGD_VENDOR_DESCRIPTION_SIZE);
421 spd.source_device = SDVO_HDMI_SPD_SOURCE_PC;
424 for (i= 0; i < SDVO_HDMI_SPD_BUFFER_SIZE; i++) {
427 spd.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
429 /* Send data to SDVO device */
430 status = sdvo_hdmi_write_buffer
431 (p_ctx, SDVO_HDMI_SPD_BUFFER, 0, spd.data, SDVO_HDMI_SPD_BUFFER_SIZE);
434 /* ============================================================================
435 Function : sdvo_hdmi_write_buffer
439 Remarks : Write into SDVO buffers
442 ------------------------------------------------------------------------- */
443 sdvo_status_t sdvo_hdmi_write_buffer
444 (sdvo_device_context_t *p_ctx,unsigned char index,
445 unsigned char offset, unsigned char *input, int len)
447 sdvo_status_t status;
448 i2c_reg_t hdmi_index[2],data[8];
450 unsigned char total_bytes, *p_sdvo_buffer, *ori_p_sdvo_buffer;
452 /* Set Buffer index and offset */
453 hdmi_index[0] = index;
454 hdmi_index[1] = offset;
455 status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_INDEX,
458 if (status != SS_SUCCESS) {
459 PD_ERROR("HDMI wirte buffer fail : Set index");
463 /* Setup buffer transmit rate */
464 if(index != SDVO_HDMI_ELD_BUFFER){
465 data[0] = SDVO_HDMI_TRANSMIT_EVERY;
466 status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_TRANSMIT_RATE,
469 if (status != SS_SUCCESS) {
470 PD_ERROR("HDMI wirte buffer fail : Transmite rate");
475 status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_TRANSMIT_RATE,
478 if (status != SS_SUCCESS) {
479 PD_ERROR("HDMI wirte buffer fail : Transmite rate");
484 /* Get buffer size info */
485 status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_INFO,
487 1, (i2c_reg_t *)&data);
488 buffer_size = data[0] + 1;
489 /* Minimum buffer size is 3 then something is wrong */
490 if (status != SS_SUCCESS || buffer_size <0x03) {
491 PD_ERROR("HDMI wirte buffer fail : Buffer size");
495 /* Make sure to query size of buffer from SDVO and use it, not size of source infoframe buffers */
496 /* copy structs into cleared memory the size of SDVO buffer */
497 p_sdvo_buffer = pd_malloc(buffer_size);
498 ori_p_sdvo_buffer = p_sdvo_buffer;
499 pd_memset(p_sdvo_buffer, 0, buffer_size);
500 pd_memcpy(p_sdvo_buffer, input, (len < buffer_size) ? len : buffer_size);
503 //total_bytes = (buffer_size >= 8) ? 8:buffer_size;
504 if(buffer_size >= 8) total_bytes = 8;
505 else total_bytes = (unsigned char)buffer_size;
507 status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_DATA,
508 total_bytes, (i2c_reg_t *)p_sdvo_buffer,
510 if (status != SS_SUCCESS) {
511 PD_ERROR("HDMI wirte buffer fail : Set buffer data");
514 p_sdvo_buffer +=total_bytes;
515 buffer_size -= total_bytes;
518 pd_free(ori_p_sdvo_buffer);
522 #endif/* SDVO_HDMI */