#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)
static void
_tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
{
- free(caps_pp->formats);
+ if (caps_pp->formats)
+ free(caps_pp->formats);
+
memset(caps_pp, 0, sizeof(tdm_caps_pp));
}
static void
_tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
{
- free(caps_capture->formats);
+ if (caps_capture->formats)
+ free(caps_capture->formats);
+
memset(caps_capture, 0, sizeof(tdm_caps_capture));
}
static void
_tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
{
- free(caps_layer->formats);
- free(caps_layer->props);
+ if (caps_layer->formats)
+ free(caps_layer->formats);
+
+ if (caps_layer->props)
+ free(caps_layer->props);
+
memset(caps_layer, 0, sizeof(tdm_caps_layer));
}
static void
_tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
{
- free(caps_output->modes);
- free(caps_output->props);
+ if (caps_output->modes)
+ free(caps_output->modes);
+
+ if (caps_output->props)
+ free(caps_output->props);
+
memset(caps_output, 0, sizeof(tdm_caps_output));
}
free(m);
}
- LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
+ 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);
}
}
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);
return ret;
}
-INTERN void
-tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
- void *user_data)
-{
- tdm_private_display *private_display;
- tdm_private_output *private_output = user_data;
- tdm_value value;
-
- TDM_RETURN_IF_FAIL(private_output);
-
- private_display = private_output->private_display;
-
- if (!tdm_thread_in_display_thread(private_display)) {
- tdm_thread_cb_output_status output_status;
- tdm_error ret;
-
- output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
- output_status.base.length = sizeof output_status;
- output_status.output_stamp = private_output->stamp;
- output_status.status = status;
- output_status.user_data = user_data;
-
- ret = tdm_thread_send_cb(private_display, &output_status.base);
- TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
-
- return;
- }
-
- value.u32 = status;
- tdm_output_call_change_handler_internal(private_output,
- TDM_OUTPUT_CHANGE_CONNECTION,
- value);
-}
-
static tdm_error
_tdm_display_update_output(tdm_private_display *private_display,
tdm_output *output_backend, int pipe)
while (tdm_display_find_output_stamp(private_display, private_output->stamp))
private_output->stamp++;
- LIST_ADD(&private_output->link, &private_display->output_list);
+ 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);
-
- if (func_output->output_set_status_handler) {
- private_output->regist_change_cb = 1;
- ret = func_output->output_set_status_handler(output_backend,
- tdm_output_cb_status,
- private_output);
- if (ret != TDM_ERROR_NONE)
- goto failed_update;
- }
+ 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 = 0, index_lvds = 0, index_hdmia = 0, index_hdmib = 0;
+ 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;
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++) {
const char *name;
const char *vendor;
int major, minor;
- int abimaj, abimin;
- abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
- abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
-
- TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
+ TDM_INFO("TDM ABI version : %d.%d",
+ TDM_MAJOR_VERSION, TDM_MINOR_VERSION);
name = module->name ? module->name : "unknown";
vendor = module->vendor ? module->vendor : "unknown";
TDM_INFO("'%s' vendor: %s", name, vendor);
TDM_INFO("'%s' version: %d.%d", name, major, minor);
- if (major != abimaj) {
- TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
+ if (major != TDM_MAJOR_VERSION) {
+ TDM_ERR("'%s' major version mismatch, %d != %d",
+ name, major, TDM_MAJOR_VERSION);
return TDM_ERROR_BAD_MODULE;
}
- if (minor > abimin) {
- TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
+ if (minor > TDM_MINOR_VERSION) {
+ TDM_ERR("'%s' minor version(%d) is newer than %d",
+ name, minor, TDM_MINOR_VERSION);
return TDM_ERROR_BAD_MODULE;
}
goto failed_mutex_init;
}
- ret = tdm_event_init(private_display);
- if (ret != TDM_ERROR_NONE)
- goto failed_event;
+ _pthread_mutex_lock(&private_display->lock);
- ret = tdm_thread_init(private_display);
+ ret = tdm_event_loop_init(private_display);
if (ret != TDM_ERROR_NONE)
- goto failed_thread;
+ 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_create_backend_source(private_display);
+ tdm_event_loop_create_backend_source(private_display);
private_display->init_count = 1;
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_thread_deinit(private_display);
-failed_thread:
- tdm_event_deinit(private_display);
+ 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_thread_deinit(private_display);
- tdm_event_deinit(private_display);
+ 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");
+}
+
+INTERN int
+tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin)
+{
+ tdm_backend_module *module = private_display->module_data;
+
+ if (TDM_BACKEND_GET_ABI_MAJOR(module->abi_version) < abimaj)
+ return 0;
+
+ if (TDM_BACKEND_GET_ABI_MINOR(module->abi_version) < abimin)
+ return 0;
+
+ return 1;
}