1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Jason Hu <jason.hu@intel.com>
26 */
27
28#include "psb_HDMIExtMode.h"
29#include "psb_output_android.h"
30#include "pvr2d.h"
31#include "psb_drv_video.h"
32#include "psb_drv_debug.h"
33
34#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
35
36VAStatus psb_HDMIExt_get_prop(psb_android_output_p output,
37                              unsigned short *xres, unsigned short *yres)
38{
39    psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info;
40
41    if (!psb_HDMIExt_info || !psb_HDMIExt_info->hdmi_extvideo_prop ||
42        (psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode == OFF)) {
43        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get HDMI prop\n", __FUNCTION__);
44        return VA_STATUS_ERROR_UNKNOWN;
45    }
46    *xres = psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode_XRes;
47    *yres = psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode_YRes;
48
49    return VA_STATUS_SUCCESS;
50}
51
52psb_hdmi_mode psb_HDMIExt_get_mode(psb_android_output_p output)
53{
54    psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info;
55
56    if (!psb_HDMIExt_info) {
57        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get HDMI mode\n", __FUNCTION__);
58        return VA_STATUS_ERROR_UNKNOWN;
59    }
60    return psb_HDMIExt_info->hdmi_mode;
61}
62
63VAStatus psb_HDMIExt_update(VADriverContextP ctx, psb_HDMIExt_info_p psb_HDMIExt_info)
64{
65    INIT_DRIVER_DATA;
66    drmModeCrtc *hdmi_crtc = NULL;
67    drmModeConnector *hdmi_connector = NULL;
68    drmModeEncoder *hdmi_encoder = NULL;
69    char *strHeight = NULL;
70    struct drm_lnc_video_getparam_arg arg;
71    int hdmi_state = 0;
72    static int hdmi_connected_frame = 0;
73
74    arg.key = IMG_VIDEO_GET_HDMI_STATE;
75    arg.value = (uint64_t)((unsigned int)&hdmi_state);
76    drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
77                        &arg, sizeof(arg));
78
79    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : hdmi_state = %d\n", __FUNCTION__, hdmi_state);
80    if (psb_HDMIExt_info->hdmi_state != hdmi_state) {
81        psb_HDMIExt_info->hdmi_state = hdmi_state;
82        switch (hdmi_state) {
83            case HDMI_MODE_EXT_VIDEO:
84                psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode = EXTENDED_VIDEO;
85                psb_HDMIExt_info->hdmi_mode = EXTENDED_VIDEO;
86
87                psb_extvideo_prop_p hdmi_extvideo_prop = psb_HDMIExt_info->hdmi_extvideo_prop;
88
89                hdmi_connector = drmModeGetConnector(driver_data->drm_fd, psb_HDMIExt_info->hdmi_connector_id);
90                if (!hdmi_connector) {
91                    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get hdmi connector\n", __FUNCTION__);
92                    return VA_STATUS_ERROR_UNKNOWN;
93                }
94
95                hdmi_encoder = drmModeGetEncoder(driver_data->drm_fd, hdmi_connector->encoder_id);
96                if (!hdmi_encoder) {
97                    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get hdmi encoder\n", __FUNCTION__);
98                    return VA_STATUS_ERROR_UNKNOWN;
99                }
100
101                hdmi_crtc = drmModeGetCrtc(driver_data->drm_fd, hdmi_encoder->crtc_id);
102                if (!hdmi_crtc) {
103                    /* No CRTC attached to HDMI. */
104                    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get hdmi crtc\n", __FUNCTION__);
105                    return VA_STATUS_ERROR_UNKNOWN;
106                }
107
108                strHeight = strstr(hdmi_crtc->mode.name, "x");
109                hdmi_extvideo_prop->ExtVideoMode_XRes = (unsigned short)atoi(hdmi_crtc->mode.name);
110                hdmi_extvideo_prop->ExtVideoMode_YRes = (unsigned short)atoi(strHeight + 1);
111                drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : size = %d x %d\n", __FUNCTION__,
112                        hdmi_extvideo_prop->ExtVideoMode_XRes, hdmi_extvideo_prop->ExtVideoMode_YRes);
113                drmModeFreeCrtc(hdmi_crtc);
114                drmModeFreeEncoder(hdmi_encoder);
115                drmModeFreeConnector(hdmi_connector);
116                break;
117            case HDMI_MODE_OFF:
118                psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode = OFF;
119                psb_HDMIExt_info->hdmi_mode = OFF;
120                hdmi_connected_frame = 0;
121                break;
122            default:
123                psb_HDMIExt_info->hdmi_extvideo_prop->ExtVideoMode = UNDEFINED;
124                psb_HDMIExt_info->hdmi_mode = UNDEFINED;
125        }
126    }
127
128    return VA_STATUS_SUCCESS;
129}
130
131psb_HDMIExt_info_p psb_HDMIExt_init(VADriverContextP ctx, psb_android_output_p output)
132{
133    INIT_DRIVER_DATA;
134    drmModeRes *resources;
135    drmModeConnector *connector = NULL;
136    drmModeEncoder *mipi_encoder = NULL;
137    int mipi_connector_id = 0, mipi_encoder_id = 0, mipi_crtc_id = 0, i;
138    psb_HDMIExt_info_p psb_HDMIExt_info = NULL;
139
140    psb_HDMIExt_info = (psb_HDMIExt_info_p)calloc(1, sizeof(psb_HDMIExt_info_s));
141    if (!psb_HDMIExt_info) {
142        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to create psb_HDMIExt_info.\n", __FUNCTION__);
143        return NULL;
144    }
145    memset(psb_HDMIExt_info, 0, sizeof(psb_HDMIExt_info_s));
146
147    psb_HDMIExt_info->hdmi_extvideo_prop = (psb_extvideo_prop_p)calloc(1, sizeof(psb_extvideo_prop_s));
148    if (!psb_HDMIExt_info->hdmi_extvideo_prop) {
149        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to create hdmi_extvideo_prop.\n", __FUNCTION__);
150        free(psb_HDMIExt_info);
151        return NULL;
152    }
153    memset(psb_HDMIExt_info->hdmi_extvideo_prop, 0, sizeof(psb_extvideo_prop_s));
154
155    /*Get Resources.*/
156    resources = drmModeGetResources(driver_data->drm_fd);
157    if (!resources) {
158        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : drmModeGetResources failed.\n", __FUNCTION__);
159        goto exit;
160    }
161
162    /*Get MIPI and HDMI connector id.*/
163    for (i = 0; i < resources->count_connectors; i++) {
164        connector = drmModeGetConnector(driver_data->drm_fd, resources->connectors[i]);
165
166        if (!connector) {
167            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get connector %i\n", __FUNCTION__,
168                               resources->connectors[i]);
169            continue;
170        }
171
172        if (connector->connector_type == DRM_MODE_CONNECTOR_DVID)
173            psb_HDMIExt_info->hdmi_connector_id = connector->connector_id;
174
175        if ((connector->connector_type == DRM_MODE_CONNECTOR_MIPI) &&
176            (!mipi_connector_id)) {
177            mipi_connector_id = connector->connector_id;
178            mipi_encoder_id = connector->encoder_id;
179        }
180
181        drmModeFreeConnector(connector);
182        connector = NULL;
183    }
184
185    if (!mipi_connector_id ||
186        !psb_HDMIExt_info->hdmi_connector_id ||
187        !mipi_encoder_id) {
188        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get connector id or mipi encoder id. mipi_connector_id=%d, hdmi_connector_id=%d, mipi_encoder_id=%d\n", __FUNCTION__,
189                           mipi_connector_id, psb_HDMIExt_info->hdmi_connector_id, mipi_encoder_id);
190        goto exit;
191    }
192
193    mipi_encoder = drmModeGetEncoder(driver_data->drm_fd, mipi_encoder_id);
194    if (!mipi_encoder) {
195        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s : Failed to get mipi encoder %i\n", __FUNCTION__);
196        goto exit;
197    }
198
199    psb_HDMIExt_info->mipi_crtc_id = mipi_encoder->crtc_id;
200    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : mipi_crtc_id = %d\n", __FUNCTION__,
201                             mipi_crtc_id);
202
203    drmModeFreeEncoder(mipi_encoder);
204
205    if (psb_HDMIExt_update(ctx, psb_HDMIExt_info))
206        goto exit;
207
208    if (resources)
209        drmModeFreeResources(resources);
210
211    return psb_HDMIExt_info;
212
213exit:
214    if (resources)
215        drmModeFreeResources(resources);
216
217    if (connector)
218        drmModeFreeConnector(connector);
219
220    return psb_HDMIExt_info;
221}
222
223VAStatus psb_HDMIExt_deinit(psb_android_output_p output)
224{
225    psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info;
226
227    if (psb_HDMIExt_info->hdmi_extvideo_prop)
228        free(psb_HDMIExt_info->hdmi_extvideo_prop);
229
230    if (psb_HDMIExt_info)
231        free(psb_HDMIExt_info);
232
233    return VA_STATUS_SUCCESS;
234}
235
236