}
#endif
+static hal_tdm_error
+_tdm_sprd_timer_fd_handler(int fd, hal_tdm_event_loop_mask mask, void *user_data)
+{
+ tdm_sprd_display *display_data = (tdm_sprd_display *)user_data;
+
+ TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
+
+ tdm_sprd_capture_timer_cb(display_data);
+
+ return HAL_TDM_ERROR_NONE;
+}
+
static int
_tdm_sprd_open_drm(void)
{
static void
_tdm_sprd_display_deinitialize(tdm_sprd_display *display_data)
{
+ tdm_sprd_capture_deinit(display_data);
tdm_sprd_display_destroy_output_list(display_data);
tdm_sprd_display_destroy_buffer_list(display_data);
static hal_tdm_error
_tdm_sprd_master_drm_fd_handler(hal_tdm_fd master_drm_fd, void *user_data)
{
- tdm_sprd_display *display_data = (tdm_sprd_display *) user_data;
+ tdm_sprd_display *display_data = (tdm_sprd_display *)user_data;
hal_tdm_error ret;
TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
_tdm_sprd_display_deinitialize(display_data);
+ if (display_data->timer_fd >= 0)
+ close(display_data->timer_fd);
+
if (display_data->drm_fd >= 0)
close(display_data->drm_fd);
tdm_sprd_display *display_data = NULL;
hal_tdm_error ret;
int drm_fd;
+ int timer_fd;
+ hal_tdm_event_source *timer_event_source;
/* allocate a hal_tdm_backend_data */
backend_data = calloc(1, sizeof(struct _hal_tdm_backend_data));
TDM_BACKEND_INFO("A backend requests an master drm_fd.\n");
}
+ /* create timer fd */
+ timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (timer_fd > 0) {
+ timer_event_source = calloc(1, sizeof(struct _hal_tdm_event_source));
+ if (!timer_event_source) {
+ TDM_BACKEND_ERR("fail to alloc udev_event_source!\n");
+ goto failed;
+ }
+ timer_event_source->event_fd = timer_fd;
+ timer_event_source->func = _tdm_sprd_timer_fd_handler;
+ timer_event_source->user_data = display_data;
+ display_data->timer_fd = timer_fd;
+
+ backend_data->event_sources[0] = timer_event_source;
+ backend_data->num_event_sources++;
+
+ TDM_BACKEND_INFO("make timer_fd.%d\n", display_data->timer_fd);
+ } else {
+ TDM_BACKEND_ERR("fail to timerfd_create!\n");
+ display_data->timer_fd = -1;
+ }
+ ret = tdm_sprd_capture_init(display_data);
+ if (ret != HAL_TDM_ERROR_NONE)
+ goto failed;
+
/* alloc and register display_funcs */
display_funcs = calloc(1, sizeof(struct _hal_tdm_display_funcs));
if (!display_funcs) {
struct list_head pending_buffer_list;
struct list_head pp_convert_list;
struct list_head composite_list;
-#if 0
- struct {
- tdm_event_loop_source *timer_source;
- } stream;
-#endif
+
hal_tdm_capture_done_handler done_func;
void *done_user_data;
struct list_head link;
} tdm_sprd_capture_data;
+typedef struct _tdm_sprd_capture_internal {
+ tdm_sprd_capture_data *stream_data;
+ int timer_fd;
+ int removing;
+ int timer_running;
+} tdm_sprd_capture_internal;
+
+static tdm_sprd_capture_internal *g_capture_data;
+
static tbm_format capture_client_formats[] = {
TBM_FORMAT_XRGB8888,
TBM_FORMAT_ARGB8888,
return tdm_err;
}
+static hal_tdm_error
+_tdm_sprd_capture_set_timer(tdm_sprd_capture_data *capture_data)
+{
+ struct itimerspec timeout;
+ int ret = 0;
+
+ timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
+ timeout.it_value.tv_nsec = 30000000;
+ timeout.it_interval.tv_nsec = 30000000; /* 30ms interval */
+// timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = (1000000000.0 / capture_data->info.frequency) + 1000000;
+
+ ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
+ if (ret) {
+ TDM_BACKEND_ERR("timerfd_settime fail : %d", errno);
+ return HAL_TDM_ERROR_OPERATION_FAILED;
+ }
+
+ TDM_BACKEND_DBG("set timer %llu", timeout.it_interval.tv_nsec);
+
+ return HAL_TDM_ERROR_NONE;
+}
+
+static hal_tdm_error
+_tdm_sprd_capture_stop_timer(void)
+{
+ struct itimerspec timeout;
+ int ret = 0;
+
+ timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
+ timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = 0;
+
+ ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
+ if (ret) {
+ TDM_BACKEND_ERR("timerfd_settime stop fail : %d", errno);
+ return HAL_TDM_ERROR_OPERATION_FAILED;
+ }
+
+ TDM_BACKEND_DBG("stop timer");
+
+ return HAL_TDM_ERROR_NONE;
+}
+
+
void
sprd_capture_destroy(hal_tdm_capture *capture)
{
}
free(b);
}
-#if 0
- if (capture_data->stream.timer_source) {
- TDM_BACKEND_DBG("capture %p removing postponed", capture_data);
- return;
+
+ if (g_capture_data->stream_data == capture_data) {
+ if (g_capture_data->timer_running == 1) {
+ TDM_BACKEND_DBG("capture %p removing postponed", capture_data);
+ return;
+ }
+ g_capture_data->stream_data = NULL;
+ g_capture_data->timer_running = 0;
+ _tdm_sprd_capture_stop_timer();
}
-#endif
+
LIST_DEL(&capture_data->link);
capture_data->stamp = 0;
tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
free(capture_data);
}
-#if 0
+
static hal_tdm_error
-_tdm_sprd_capture_stream_timer_handler(void *user_data)
+_tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
{
- tdm_sprd_capture_data *capture_data = user_data;
- if (!_tdm_sprd_capture_check_struct(user_data)) {
- return HAL_TDM_ERROR_NONE;
- }
+ hal_tdm_error ret;
- if (capture_data->removing) {
- TDM_BACKEND_DBG("Capture %p Postponded removing", capture_data);
- tdm_event_loop_source_remove(capture_data->stream.timer_source);
- LIST_DEL(&capture_data->link);
- capture_data->stamp = 0;
- tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
- free(capture_data);
- return HAL_TDM_ERROR_NONE;
+ if (g_capture_data->timer_fd == -1) {
+ TDM_BACKEND_ERR("cannot support stream capture");
+ return HAL_TDM_ERROR_BAD_REQUEST;
}
- unsigned int ms = 1000 / capture_data->info.frequency;
- tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
- tbm_surface_h current_buffer = NULL;
- hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
- if (!capture_data->stream.timer_source) {
- TDM_BACKEND_ERR("Timer removed");
- return HAL_TDM_ERROR_NONE;
+
+ if ((g_capture_data->stream_data != NULL) && (g_capture_data->stream_data != capture_data)) {
+ TDM_BACKEND_ERR("previous stream capture is working. cannot execute.");
+ return HAL_TDM_ERROR_BUSY;
}
- tdm_event_loop_source_timer_update(capture_data->stream.timer_source, ms);
- if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
- TDM_BACKEND_DBG("Converter is busy");
+
+ if (g_capture_data->timer_running) {
+ TDM_BACKEND_DBG("stream capture is working");
return HAL_TDM_ERROR_NONE;
}
- LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
- LIST_DEL(&b->link);
- current_buffer = tbm_surface_internal_ref(b->buffer);
- free(b);
- tdm_err = _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
- tbm_surface_internal_unref(current_buffer);
- break;
+
+ ret = _tdm_sprd_capture_set_timer(capture_data);
+ if (ret != HAL_TDM_ERROR_NONE) {
+ TDM_BACKEND_ERR("timerfd_settime fail: %d", ret);
+ return HAL_TDM_ERROR_OPERATION_FAILED;
}
- return tdm_err;
-}
-#endif
-static hal_tdm_error
-_tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
-{
-#if 0
- unsigned int ms = 1000 / capture_data->info.frequency;
+ g_capture_data->timer_running = 1;
+ g_capture_data->stream_data = capture_data;
- if (!capture_data->stream.timer_source) {
- capture_data->stream.timer_source =
- tdm_event_loop_add_timer_handler(capture_data->display_data->dpy,
- _tdm_sprd_capture_stream_timer_handler,
- capture_data, NULL);
- TDM_BACKEND_RETURN_VAL_IF_FAIL(capture_data->stream.timer_source != NULL, HAL_TDM_ERROR_OUT_OF_MEMORY);
- }
+ TDM_BACKEND_INFO("stream capture start");
- tdm_event_loop_source_timer_update(capture_data->stream.timer_source, ms);
-#endif
return HAL_TDM_ERROR_NONE;
}
sprd_display_get_capture_capability(hal_tdm_display *display, hal_tdm_caps_capture *caps)
{
int i;
+ tdm_sprd_display *display_data = NULL;
if (!caps || !display) {
TDM_BACKEND_ERR("invalid params");
return HAL_TDM_ERROR_INVALID_PARAMETER;
}
+ display_data = (tdm_sprd_display *)display;
+
caps->capabilities = HAL_TDM_CAPTURE_CAPABILITY_OUTPUT|
HAL_TDM_CAPTURE_CAPABILITY_ONESHOT;
-// HAL_TDM_CAPTURE_CAPABILITY_STREAM;
+ if (display_data->timer_fd != -1)
+ caps->capabilities |= HAL_TDM_CAPTURE_CAPABILITY_STREAM;
caps->format_count = NUM_CAPTURE_FORMAT;
caps->formats = NULL;
TDM_BACKEND_DBG("capture %p set done handler func %p", capture, func);
return HAL_TDM_ERROR_NONE;
}
+
+hal_tdm_error
+tdm_sprd_capture_init(tdm_sprd_display *display_data)
+{
+ tdm_sprd_capture_internal *capture_data_internal = calloc(1, sizeof(tdm_sprd_capture_internal));
+ if (!capture_data_internal) {
+ TDM_BACKEND_ERR("alloc failed");
+
+ return HAL_TDM_ERROR_OUT_OF_MEMORY;
+ }
+ capture_data_internal->timer_fd = display_data->timer_fd;
+
+ g_capture_data = capture_data_internal;
+
+ return HAL_TDM_ERROR_NONE;
+}
+
+void
+tdm_sprd_capture_deinit(tdm_sprd_display *display_data)
+{
+ if (g_capture_data == NULL)
+ return;
+
+ free(g_capture_data);
+ g_capture_data = NULL;
+}
+
+void
+tdm_sprd_capture_timer_cb(tdm_sprd_display *display_data)
+{
+ tdm_sprd_capture_data *capture_data = NULL;
+ tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
+ tbm_surface_h current_buffer = NULL;
+ uint64_t buf;
+ int expired = read(display_data->timer_fd, &buf, sizeof(uint64_t));
+ if (expired < 0)
+ TDM_BACKEND_ERR("read fail");
+
+ if (g_capture_data == NULL || g_capture_data->stream_data == NULL)
+ return;
+
+ capture_data = g_capture_data->stream_data;
+ if (!_tdm_sprd_capture_check_struct(capture_data))
+ return;
+
+ if (capture_data->removing) {
+ TDM_BACKEND_INFO("Capture %p Postponded removing", capture_data);
+ _tdm_sprd_capture_stop_timer();
+ g_capture_data->timer_running = 0;
+ g_capture_data->stream_data = NULL;
+ LIST_DEL(&capture_data->link);
+ capture_data->stamp = 0;
+ tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
+ free(capture_data);
+ return;
+ }
+
+ if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
+ TDM_BACKEND_DBG("Converter is busy");
+ return;
+ }
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
+ LIST_DEL(&b->link);
+ current_buffer = b->buffer;
+ tbm_surface_internal_ref(current_buffer);
+ free(b);
+ _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
+ tbm_surface_internal_unref(current_buffer);
+ break;
+ }
+}