#include "tdm_private.h"
#include "tdm_helper.h"
+pthread_mutex_t tdm_mutex_check_lock = PTHREAD_MUTEX_INITIALIZER;
+int tdm_mutex_locked;
+
static tdm_private_layer *
_tdm_display_find_private_layer(tdm_private_output *private_output,
tdm_layer *layer_backend)
return NULL;
}
+INTERN tdm_private_output *
+tdm_display_find_output_stamp(tdm_private_display *private_display,
+ unsigned long stamp)
+{
+ tdm_private_output *private_output = NULL;
+
+ LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
+ if (private_output->stamp == stamp)
+ return private_output;
+ }
+
+ return NULL;
+}
+
static void
_tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
{
tdm_private_capture *c = NULL, *cc = NULL;
tdm_private_vblank_handler *v = NULL, *vv = NULL;
tdm_private_commit_handler *m = NULL, *mm = NULL;
+ tdm_private_change_handler *h = NULL, *hh = NULL;
LIST_DEL(&private_output->link);
free(m);
}
+ LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
+ LIST_DEL(&h->link);
+ free(h);
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
+ LIST_DEL(&h->link);
+ free(h);
+ }
+
LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
tdm_capture_destroy_internal(c);
_tdm_display_destroy_caps_output(&private_output->caps);
+ private_output->stamp = 0;
free(private_output);
}
}
static tdm_error
-_tdm_display_update_caps_output(tdm_private_display *private_display,
+_tdm_display_update_caps_output(tdm_private_display *private_display, int pipe,
tdm_output *output_backend, tdm_caps_output *caps)
{
tdm_func_output *func_output = &private_display->func_output;
+ char temp[TDM_NAME_LEN];
int i;
tdm_error ret;
return TDM_ERROR_BAD_MODULE;
}
+ /* FIXME: Use model for tdm client to distinguish amoung outputs */
+ snprintf(temp, TDM_NAME_LEN, "%s-%d", caps->model, pipe);
+ snprintf(caps->model, TDM_NAME_LEN, "%s", temp);
+
TDM_DBG("output maker: %s", caps->maker);
TDM_DBG("output model: %s", caps->model);
TDM_DBG("output name: %s", caps->name);
private_output = calloc(1, sizeof(tdm_private_output));
TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
- LIST_ADD(&private_output->link, &private_display->output_list);
+ private_output->stamp = tdm_helper_get_time_in_millis();
+ while (tdm_display_find_output_stamp(private_display, private_output->stamp))
+ private_output->stamp++;
+
+ LIST_ADDTAIL(&private_output->link, &private_display->output_list);
+
private_output->private_display = private_display;
+ private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF;
private_output->output_backend = output_backend;
private_output->pipe = pipe;
LIST_INITHEAD(&private_output->capture_list);
LIST_INITHEAD(&private_output->vblank_handler_list);
LIST_INITHEAD(&private_output->commit_handler_list);
+ LIST_INITHEAD(&private_output->change_handler_list_main);
+ LIST_INITHEAD(&private_output->change_handler_list_sub);
+
+ if (func_output->output_set_status_handler)
+ func_output->output_set_status_handler(private_output->output_backend,
+ tdm_output_cb_status,
+ private_output);
+
} else
_tdm_display_destroy_caps_output(&private_output->caps);
- ret = _tdm_display_update_caps_output(private_display, output_backend,
+ ret = _tdm_display_update_caps_output(private_display, pipe, output_backend,
&private_output->caps);
if (ret != TDM_ERROR_NONE)
return ret;
return ret;
}
+static tdm_output **
+_tdm_display_set_main_first(tdm_output **outputs, int index)
+{
+ tdm_output *output_tmp = NULL;
+
+ if (index == 0)
+ return outputs;
+
+ output_tmp = outputs[0];
+ outputs[0] = outputs[index];
+ outputs[index] = output_tmp;
+
+ return outputs;
+}
+
+static tdm_output **
+_tdm_display_get_ordered_outputs(tdm_private_display *private_display,
+ int *count, int init)
+{
+ tdm_func_display *func_display = &private_display->func_display;
+ tdm_output **outputs = NULL;
+ tdm_output **new_outputs = NULL;
+ tdm_output *output_dsi = NULL;
+ tdm_output *output_lvds = NULL;
+ tdm_output *output_hdmia = NULL;
+ tdm_output *output_hdmib = NULL;
+ int i, output_count = 0, output_connected_count = 0;
+ int index_dsi, index_lvds, index_hdmia, index_hdmib;
+ tdm_error ret;
+
+ outputs = func_display->display_get_outputs(private_display->bdata,
+ &output_count, &ret);
+ if (ret != TDM_ERROR_NONE)
+ goto failed_get_outputs;
+
+ *count = output_count;
+
+ if (output_count == 0)
+ goto failed_get_outputs;
+ else if (output_count == 1)
+ return outputs;
+
+ /* don't change list order if not init time */
+ if (init != 0)
+ return outputs;
+
+ /* count connected outputs */
+ for (i = 0; i < output_count; i++) {
+ tdm_func_output *func_output = &private_display->func_output;
+ tdm_caps_output caps;
+ memset(&caps, 0, sizeof(tdm_caps_output));
+
+ if (!func_output->output_get_capability) {
+ TDM_ERR("no output_get_capability()");
+ return outputs;
+ }
+
+ ret = func_output->output_get_capability(outputs[i], &caps);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("output_get_capability() failed");
+ return outputs;
+ }
+
+ if (caps.status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
+ output_connected_count++;
+
+ switch (caps.type) {
+ case TDM_OUTPUT_TYPE_DSI:
+ output_dsi = outputs[i];
+ index_dsi = i;
+ break;
+ case TDM_OUTPUT_TYPE_LVDS:
+ output_lvds = outputs[i];
+ index_lvds = i;
+ break;
+ case TDM_OUTPUT_TYPE_HDMIA:
+ output_hdmia = outputs[i];
+ index_hdmia = i;
+ break;
+ case TDM_OUTPUT_TYPE_HDMIB:
+ output_hdmib = outputs[i];
+ index_hdmib = i;
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ /* ordering : main output is first */
+ /* If there is no connected output, lvds or dsi cannot be main display. (cannot connect after booting)
+ * But hdmi is possible, so set hdmi to main display.
+ * If connected only one output, it is main output.
+ * If connected outputs over 2, has priority like below.
+ * (dsi > lvds > hdmi > else)
+ */
+ if (output_connected_count == 0) {
+ /* hdmi > dsi > lvds > else */
+ if (output_hdmia != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_hdmia);
+ else if (output_hdmib != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_hdmib);
+ else if (output_dsi != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_dsi);
+ else if (output_lvds != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_lvds);
+ else
+ new_outputs = outputs;
+ } else { /* (output_connected_count > 1) */
+ /* dsi > lvds > hdmi > else */
+ if (output_dsi != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_dsi);
+ else if (output_lvds != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_lvds);
+ else if (output_hdmia != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_hdmia);
+ else if (output_hdmib != NULL)
+ new_outputs = _tdm_display_set_main_first(outputs, index_hdmib);
+ else
+ new_outputs = outputs;
+ }
+
+ return new_outputs;
+
+failed_get_outputs:
+ *count = 0;
+ return NULL;
+}
+
static tdm_error
_tdm_display_update_internal(tdm_private_display *private_display,
int only_display)
{
- tdm_func_display *func_display = &private_display->func_display;
tdm_output **outputs = NULL;
int output_count = 0, i;
tdm_error ret;
LIST_INITHEAD(&private_display->output_list);
LIST_INITHEAD(&private_display->pp_list);
+ LIST_INITHEAD(&private_display->capture_list);
if (!only_display) {
ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
goto failed_update;
}
- outputs = func_display->display_get_outputs(private_display->bdata,
- &output_count, &ret);
- if (ret != TDM_ERROR_NONE)
+ outputs = _tdm_display_get_ordered_outputs(private_display, &output_count, only_display);
+ if (!outputs)
goto failed_update;
for (i = 0; i < output_count; i++) {
int tdm_debug;
int tdm_debug_buffer;
+int tdm_debug_thread;
int tdm_debug_mutex;
static tdm_private_display *g_private_display;
if (debug && (strstr(debug, "1")))
tdm_debug_buffer = 1;
+ debug = getenv("TDM_DEBUG_THREAD");
+ if (debug && (strstr(debug, "1")))
+ tdm_debug_thread = 1;
+
debug = getenv("TDM_DEBUG_MUTEX");
if (debug && (strstr(debug, "1")))
tdm_debug_mutex = 1;
goto failed_mutex_init;
}
+ _pthread_mutex_lock(&private_display->lock);
+
+ ret = tdm_event_loop_init(private_display);
+ if (ret != TDM_ERROR_NONE)
+ goto failed_event;
+
ret = _tdm_display_load_module(private_display);
if (ret != TDM_ERROR_NONE)
goto failed_load;
+#ifdef INIT_BUFMGR
+ int tdm_drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
+ if (tdm_drm_fd >= 0) {
+ private_display->bufmgr = tbm_bufmgr_init(tdm_drm_fd);
+ close(tdm_drm_fd);
+ if (!private_display->bufmgr) {
+ TDM_ERR("tbm_bufmgr_init failed");
+ goto failed_update;
+ } else {
+ TDM_INFO("tbm_bufmgr_init successed");
+ }
+ }
+#endif
+
TDM_TRACE_BEGIN(Update_Display);
ret = _tdm_display_update_internal(private_display, 0);
TDM_TRACE_END();
if (ret != TDM_ERROR_NONE)
goto failed_update;
+ tdm_event_loop_create_backend_source(private_display);
+
private_display->init_count = 1;
g_private_display = private_display;
if (error)
*error = TDM_ERROR_NONE;
+ _pthread_mutex_unlock(&private_display->lock);
_pthread_mutex_unlock(&gLock);
return (tdm_display *)private_display;
failed_update:
_tdm_display_unload_module(private_display);
failed_load:
+ tdm_event_loop_deinit(private_display);
+failed_event:
+ _pthread_mutex_unlock(&private_display->lock);
pthread_mutex_destroy(&private_display->lock);
failed_mutex_init:
free(private_display);
_pthread_mutex_lock(&private_display->lock);
+ tdm_event_loop_deinit(private_display);
+
_tdm_display_destroy_private_display(private_display);
_tdm_display_unload_module(private_display);
+#ifdef INIT_BUFMGR
+ if (private_display->bufmgr)
+ tbm_bufmgr_deinit(private_display->bufmgr);
+#endif
+
tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
_pthread_mutex_unlock(&private_display->lock);
tdm_debug_buffer = 0;
_pthread_mutex_unlock(&gLock);
+
+ TDM_INFO("done");
}