Loading drivers/media/platform/msm/vpu/vpu_ioctl.c +125 −14 Original line number Diff line number Diff line Loading @@ -42,6 +42,9 @@ extern int vpu_init_port_mdss(struct vpu_dev_session *session, (session)->port_info[port].port_ops.priv) : 0) /* * Events/Callbacks handling * * Notify events of given type ID. * If data is not null then it points to a payload of predefined size (<=64). */ static void __prepare_v4l2_event(struct v4l2_event *event, u32 type, u8 *data, u32 size) Loading @@ -55,7 +58,7 @@ static void __prepare_v4l2_event(struct v4l2_event *event, memcpy(event->u.data, data, size); } void notify_vpu_event_client(struct vpu_client *client, static void notify_vpu_event_client(struct vpu_client *client, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; Loading @@ -66,7 +69,7 @@ void notify_vpu_event_client(struct vpu_client *client, v4l2_event_queue_fh(&client->vfh, &event); } void notify_vpu_event_session(struct vpu_dev_session *session, static void notify_vpu_event_session(struct vpu_dev_session *session, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; Loading @@ -80,6 +83,28 @@ void notify_vpu_event_session(struct vpu_dev_session *session, v4l2_event_queue_fh(&clnt->vfh, &event); } static void notify_vpu_event_system(struct vpu_dev_core *core, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; struct vpu_client *clnt, *n; int i; if (!core) return; __prepare_v4l2_event(&event, type, data, size); for (i = 0; i < VPU_NUM_SESSIONS; i++) { list_for_each_entry_safe(clnt, n, &core->sessions[i]->clients_list, clients_entry) v4l2_event_queue_fh(&clnt->vfh, &event); } list_for_each_entry_safe(clnt, n, &core->unattached_list, clients_entry) v4l2_event_queue_fh(&clnt->vfh, &event); } /* __system_callback_handler * * event: see enum vpu_chan_event defined in vpu_channel.h Loading Loading @@ -315,20 +340,17 @@ int vpu_close_client(struct vpu_client *client) return 0; } int vpu_attach_client(struct vpu_client *client, int session_num) static int __vpu_attach_client(struct vpu_client *client, struct vpu_dev_session *session) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret = 0; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session attach # %d\n", session_num); return -EINVAL; } if (!client) return -EINVAL; core = client->core; session = core->sessions[session_num]; pr_debug("Attach client %p to session %d\n", client, session_num); pr_debug("Attach client %p to session %d\n", client, session->id); if (client->session == session) { return 0; /* client already attached to this session */ Loading @@ -340,8 +362,6 @@ int vpu_attach_client(struct vpu_client *client, int session_num) if (session->client_count >= VPU_MAX_CLIENTS_PER_SESSION) return -EBUSY; mutex_lock(&session->lock); if (session->client_count++ == 0) { /* Initialize session controller */ Loading @@ -358,15 +378,17 @@ int vpu_attach_client(struct vpu_client *client, int session_num) pr_err("could not open IPC channel\n"); goto err_deinit_controller; } notify_vpu_event_system(core, VPU_EVENT_SESSION_CREATED, (u8 *)&session->id, sizeof(session->id)); } /* remove from unattached_list and add to session's clients list */ list_del_init(&client->clients_entry); list_add_tail(&client->clients_entry, &session->clients_list); client->session = session; mutex_unlock(&session->lock); pr_debug("Attach to session %d successful\n", session_num); pr_debug("Attach to session %d successful\n", session->id); return 0; err_deinit_controller: Loading @@ -374,7 +396,87 @@ err_deinit_controller: session->controller = NULL; err_dec_count: session->client_count--; return ret; } int vpu_create_session(struct vpu_client *client) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret, i; if (!client) return -EINVAL; core = client->core; /* find an inactive session */ for (i = 0; i < VPU_NUM_SESSIONS; i++) { session = core->sessions[i]; mutex_lock(&session->lock); if (session->client_count > 0) { mutex_unlock(&session->lock); } else { ret = __vpu_attach_client(client, session); if (ret) pr_err("Failed attach, ret = %d\n", ret); else ret = session->id; /* return session number */ mutex_unlock(&session->lock); return ret; } } pr_warn("No idle sessions available\n"); return -EBUSY; } int vpu_join_session(struct vpu_client *client, int session_num) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret = -ENODEV; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session # %d\n", session_num); return -EINVAL; } core = client->core; session = core->sessions[session_num]; mutex_lock(&session->lock); if (session->client_count == 0) pr_err("Session %d is not created yet\n", session_num); else ret = __vpu_attach_client(client, session); mutex_unlock(&session->lock); return ret; } int vpu_attach_session_deprecated(struct vpu_client *client, int session_num) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session # %d\n", session_num); return -EINVAL; } core = client->core; session = core->sessions[session_num]; mutex_lock(&session->lock); ret = __vpu_attach_client(client, session); mutex_unlock(&session->lock); return ret; } Loading Loading @@ -420,10 +522,19 @@ void vpu_detach_client(struct vpu_client *client) session->streaming_state = 0; session->commit_state = 0; session->dual_output = false; notify_vpu_event_system(client->core, VPU_EVENT_SESSION_FREED, (u8 *)&session->id, sizeof(session->id)); } list_del_init(&client->clients_entry); /* remove from attached list */ client->session = NULL; /* notify remaining session clients of the new client count */ notify_vpu_event_session(session, VPU_EVENT_SESSION_CLIENT_EXITED, (u8 *)&session->client_count, sizeof(session->client_count)); mutex_unlock(&session->lock); /* add back to global unattached list */ Loading drivers/media/platform/msm/vpu/vpu_ioctl_internal.h +5 −14 Original line number Diff line number Diff line Loading @@ -32,7 +32,11 @@ static inline int get_vpu_num_sessions(unsigned *ret) return 0; } int vpu_attach_client(struct vpu_client *client, int session_num); int vpu_create_session(struct vpu_client *client); int vpu_join_session(struct vpu_client *client, int session_num); int vpu_attach_session_deprecated(struct vpu_client *client, int session_num); void vpu_detach_client(struct vpu_client *client); Loading Loading @@ -81,19 +85,6 @@ int vpu_streamoff(struct vpu_client *client, enum v4l2_buf_type i); int vpu_trigger_stream(struct vpu_dev_session *session); /* * Notify client with event of ID type. * If data is not null then it points to payload of size (<=64) */ void notify_vpu_event_client(struct vpu_client *client, u32 type, u8 *data, u32 size); /* * Notify All clients in session with event of ID type. * If data is not null then it points to payload of size (<=64) */ void notify_vpu_event_session(struct vpu_dev_session *session, u32 type, u8 *data, u32 size); /* * Videobuf2 related functions Loading drivers/media/platform/msm/vpu/vpu_v4l2.c +18 −3 Original line number Diff line number Diff line Loading @@ -128,13 +128,28 @@ static long v4l2_vpu_private_ioctls(struct file *file, void *fh, switch (cmd) { case VPU_QUERY_SESSIONS: pr_debug("Received ioctl VPU_QUERY_SESSIONS\n"); ret = get_vpu_num_sessions((unsigned *)arg); ret = get_vpu_num_sessions((int *)arg); break; case VPU_ATTACH_TO_SESSION: pr_debug("Received ioctl VPU_ATTACH_TO_SESSION\n"); session_num = *((unsigned *)arg); ret = vpu_attach_client(client, session_num); session_num = *((int *)arg); ret = vpu_attach_session_deprecated(client, session_num); break; case VPU_CREATE_SESSION: pr_debug("Received ioctl VPU_CREATE_SESSION\n"); session_num = vpu_create_session(client); if (session_num < 0) ret = session_num; else *((int *)arg) = session_num; break; case VPU_JOIN_SESSION: pr_debug("Received ioctl VPU_JOIN_SESSION\n"); session_num = *((int *)arg); ret = vpu_join_session(client, session_num); break; case VPU_CREATE_OUTPUT2: Loading include/uapi/media/msm_vpu.h +16 −1 Original line number Diff line number Diff line Loading @@ -150,6 +150,15 @@ struct v4l2_format_vpu_extension { * VPU_EVENT_SESSION_TIMESTAMP: New Session timestamp * payload data: vpu_frame_timestamp_info * * VPU_EVENT_SESSION_CREATED: New session has been created * payload data: int (number of the attached session) * * VPU_EVENT_SESSION_FREED: Session is detached and free * payload data: int (number of the detached session) * * VPU_EVENT_SESSION_CLIENT_EXITED: Indicates that clients of current * session have exited. * payload data: int (number of all remaining clients for this session) * * VPU_EVENT_HW_ERROR: a hardware error occurred in VPU * payload data: NULL Loading @@ -167,6 +176,9 @@ enum VPU_PRIVATE_EVENT { VPU_EVENT_FLUSH_DONE = VPU_EVENT_START + 1, VPU_EVENT_ACTIVE_REGION_CHANGED = VPU_EVENT_START + 2, VPU_EVENT_SESSION_TIMESTAMP = VPU_EVENT_START + 3, VPU_EVENT_SESSION_CREATED = VPU_EVENT_START + 4, VPU_EVENT_SESSION_FREED = VPU_EVENT_START + 5, VPU_EVENT_SESSION_CLIENT_EXITED = VPU_EVENT_START + 6, VPU_EVENT_HW_ERROR = VPU_EVENT_START + 11, VPU_EVENT_INVALID_CONFIG = VPU_EVENT_START + 12, Loading Loading @@ -423,10 +435,13 @@ struct vpu_control_port { * V P U D E V I C E P R I V A T E I O C T L C O D E S */ /* VPU Session ioctls (deprecated) */ #define VPU_ATTACH_TO_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 1), int) /* VPU Session ioctls */ #define VPU_QUERY_SESSIONS _IOR('V', (BASE_VIDIOC_PRIVATE + 0), int) #define VPU_ATTACH_TO_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 1), int) #define VPU_CREATE_SESSION _IOR('V', (BASE_VIDIOC_PRIVATE + 2), int) #define VPU_JOIN_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 3), int) /* Enable second VPU output port and use with current client */ #define VPU_CREATE_OUTPUT2 _IO('V', (BASE_VIDIOC_PRIVATE + 5)) Loading Loading
drivers/media/platform/msm/vpu/vpu_ioctl.c +125 −14 Original line number Diff line number Diff line Loading @@ -42,6 +42,9 @@ extern int vpu_init_port_mdss(struct vpu_dev_session *session, (session)->port_info[port].port_ops.priv) : 0) /* * Events/Callbacks handling * * Notify events of given type ID. * If data is not null then it points to a payload of predefined size (<=64). */ static void __prepare_v4l2_event(struct v4l2_event *event, u32 type, u8 *data, u32 size) Loading @@ -55,7 +58,7 @@ static void __prepare_v4l2_event(struct v4l2_event *event, memcpy(event->u.data, data, size); } void notify_vpu_event_client(struct vpu_client *client, static void notify_vpu_event_client(struct vpu_client *client, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; Loading @@ -66,7 +69,7 @@ void notify_vpu_event_client(struct vpu_client *client, v4l2_event_queue_fh(&client->vfh, &event); } void notify_vpu_event_session(struct vpu_dev_session *session, static void notify_vpu_event_session(struct vpu_dev_session *session, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; Loading @@ -80,6 +83,28 @@ void notify_vpu_event_session(struct vpu_dev_session *session, v4l2_event_queue_fh(&clnt->vfh, &event); } static void notify_vpu_event_system(struct vpu_dev_core *core, u32 type, u8 *data, u32 size) { struct v4l2_event event = {0}; struct vpu_client *clnt, *n; int i; if (!core) return; __prepare_v4l2_event(&event, type, data, size); for (i = 0; i < VPU_NUM_SESSIONS; i++) { list_for_each_entry_safe(clnt, n, &core->sessions[i]->clients_list, clients_entry) v4l2_event_queue_fh(&clnt->vfh, &event); } list_for_each_entry_safe(clnt, n, &core->unattached_list, clients_entry) v4l2_event_queue_fh(&clnt->vfh, &event); } /* __system_callback_handler * * event: see enum vpu_chan_event defined in vpu_channel.h Loading Loading @@ -315,20 +340,17 @@ int vpu_close_client(struct vpu_client *client) return 0; } int vpu_attach_client(struct vpu_client *client, int session_num) static int __vpu_attach_client(struct vpu_client *client, struct vpu_dev_session *session) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret = 0; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session attach # %d\n", session_num); return -EINVAL; } if (!client) return -EINVAL; core = client->core; session = core->sessions[session_num]; pr_debug("Attach client %p to session %d\n", client, session_num); pr_debug("Attach client %p to session %d\n", client, session->id); if (client->session == session) { return 0; /* client already attached to this session */ Loading @@ -340,8 +362,6 @@ int vpu_attach_client(struct vpu_client *client, int session_num) if (session->client_count >= VPU_MAX_CLIENTS_PER_SESSION) return -EBUSY; mutex_lock(&session->lock); if (session->client_count++ == 0) { /* Initialize session controller */ Loading @@ -358,15 +378,17 @@ int vpu_attach_client(struct vpu_client *client, int session_num) pr_err("could not open IPC channel\n"); goto err_deinit_controller; } notify_vpu_event_system(core, VPU_EVENT_SESSION_CREATED, (u8 *)&session->id, sizeof(session->id)); } /* remove from unattached_list and add to session's clients list */ list_del_init(&client->clients_entry); list_add_tail(&client->clients_entry, &session->clients_list); client->session = session; mutex_unlock(&session->lock); pr_debug("Attach to session %d successful\n", session_num); pr_debug("Attach to session %d successful\n", session->id); return 0; err_deinit_controller: Loading @@ -374,7 +396,87 @@ err_deinit_controller: session->controller = NULL; err_dec_count: session->client_count--; return ret; } int vpu_create_session(struct vpu_client *client) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret, i; if (!client) return -EINVAL; core = client->core; /* find an inactive session */ for (i = 0; i < VPU_NUM_SESSIONS; i++) { session = core->sessions[i]; mutex_lock(&session->lock); if (session->client_count > 0) { mutex_unlock(&session->lock); } else { ret = __vpu_attach_client(client, session); if (ret) pr_err("Failed attach, ret = %d\n", ret); else ret = session->id; /* return session number */ mutex_unlock(&session->lock); return ret; } } pr_warn("No idle sessions available\n"); return -EBUSY; } int vpu_join_session(struct vpu_client *client, int session_num) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret = -ENODEV; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session # %d\n", session_num); return -EINVAL; } core = client->core; session = core->sessions[session_num]; mutex_lock(&session->lock); if (session->client_count == 0) pr_err("Session %d is not created yet\n", session_num); else ret = __vpu_attach_client(client, session); mutex_unlock(&session->lock); return ret; } int vpu_attach_session_deprecated(struct vpu_client *client, int session_num) { struct vpu_dev_core *core; struct vpu_dev_session *session; int ret; if (!client || session_num < 0 || session_num >= VPU_NUM_SESSIONS) { pr_err("invalid session # %d\n", session_num); return -EINVAL; } core = client->core; session = core->sessions[session_num]; mutex_lock(&session->lock); ret = __vpu_attach_client(client, session); mutex_unlock(&session->lock); return ret; } Loading Loading @@ -420,10 +522,19 @@ void vpu_detach_client(struct vpu_client *client) session->streaming_state = 0; session->commit_state = 0; session->dual_output = false; notify_vpu_event_system(client->core, VPU_EVENT_SESSION_FREED, (u8 *)&session->id, sizeof(session->id)); } list_del_init(&client->clients_entry); /* remove from attached list */ client->session = NULL; /* notify remaining session clients of the new client count */ notify_vpu_event_session(session, VPU_EVENT_SESSION_CLIENT_EXITED, (u8 *)&session->client_count, sizeof(session->client_count)); mutex_unlock(&session->lock); /* add back to global unattached list */ Loading
drivers/media/platform/msm/vpu/vpu_ioctl_internal.h +5 −14 Original line number Diff line number Diff line Loading @@ -32,7 +32,11 @@ static inline int get_vpu_num_sessions(unsigned *ret) return 0; } int vpu_attach_client(struct vpu_client *client, int session_num); int vpu_create_session(struct vpu_client *client); int vpu_join_session(struct vpu_client *client, int session_num); int vpu_attach_session_deprecated(struct vpu_client *client, int session_num); void vpu_detach_client(struct vpu_client *client); Loading Loading @@ -81,19 +85,6 @@ int vpu_streamoff(struct vpu_client *client, enum v4l2_buf_type i); int vpu_trigger_stream(struct vpu_dev_session *session); /* * Notify client with event of ID type. * If data is not null then it points to payload of size (<=64) */ void notify_vpu_event_client(struct vpu_client *client, u32 type, u8 *data, u32 size); /* * Notify All clients in session with event of ID type. * If data is not null then it points to payload of size (<=64) */ void notify_vpu_event_session(struct vpu_dev_session *session, u32 type, u8 *data, u32 size); /* * Videobuf2 related functions Loading
drivers/media/platform/msm/vpu/vpu_v4l2.c +18 −3 Original line number Diff line number Diff line Loading @@ -128,13 +128,28 @@ static long v4l2_vpu_private_ioctls(struct file *file, void *fh, switch (cmd) { case VPU_QUERY_SESSIONS: pr_debug("Received ioctl VPU_QUERY_SESSIONS\n"); ret = get_vpu_num_sessions((unsigned *)arg); ret = get_vpu_num_sessions((int *)arg); break; case VPU_ATTACH_TO_SESSION: pr_debug("Received ioctl VPU_ATTACH_TO_SESSION\n"); session_num = *((unsigned *)arg); ret = vpu_attach_client(client, session_num); session_num = *((int *)arg); ret = vpu_attach_session_deprecated(client, session_num); break; case VPU_CREATE_SESSION: pr_debug("Received ioctl VPU_CREATE_SESSION\n"); session_num = vpu_create_session(client); if (session_num < 0) ret = session_num; else *((int *)arg) = session_num; break; case VPU_JOIN_SESSION: pr_debug("Received ioctl VPU_JOIN_SESSION\n"); session_num = *((int *)arg); ret = vpu_join_session(client, session_num); break; case VPU_CREATE_OUTPUT2: Loading
include/uapi/media/msm_vpu.h +16 −1 Original line number Diff line number Diff line Loading @@ -150,6 +150,15 @@ struct v4l2_format_vpu_extension { * VPU_EVENT_SESSION_TIMESTAMP: New Session timestamp * payload data: vpu_frame_timestamp_info * * VPU_EVENT_SESSION_CREATED: New session has been created * payload data: int (number of the attached session) * * VPU_EVENT_SESSION_FREED: Session is detached and free * payload data: int (number of the detached session) * * VPU_EVENT_SESSION_CLIENT_EXITED: Indicates that clients of current * session have exited. * payload data: int (number of all remaining clients for this session) * * VPU_EVENT_HW_ERROR: a hardware error occurred in VPU * payload data: NULL Loading @@ -167,6 +176,9 @@ enum VPU_PRIVATE_EVENT { VPU_EVENT_FLUSH_DONE = VPU_EVENT_START + 1, VPU_EVENT_ACTIVE_REGION_CHANGED = VPU_EVENT_START + 2, VPU_EVENT_SESSION_TIMESTAMP = VPU_EVENT_START + 3, VPU_EVENT_SESSION_CREATED = VPU_EVENT_START + 4, VPU_EVENT_SESSION_FREED = VPU_EVENT_START + 5, VPU_EVENT_SESSION_CLIENT_EXITED = VPU_EVENT_START + 6, VPU_EVENT_HW_ERROR = VPU_EVENT_START + 11, VPU_EVENT_INVALID_CONFIG = VPU_EVENT_START + 12, Loading Loading @@ -423,10 +435,13 @@ struct vpu_control_port { * V P U D E V I C E P R I V A T E I O C T L C O D E S */ /* VPU Session ioctls (deprecated) */ #define VPU_ATTACH_TO_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 1), int) /* VPU Session ioctls */ #define VPU_QUERY_SESSIONS _IOR('V', (BASE_VIDIOC_PRIVATE + 0), int) #define VPU_ATTACH_TO_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 1), int) #define VPU_CREATE_SESSION _IOR('V', (BASE_VIDIOC_PRIVATE + 2), int) #define VPU_JOIN_SESSION _IOW('V', (BASE_VIDIOC_PRIVATE + 3), int) /* Enable second VPU output port and use with current client */ #define VPU_CREATE_OUTPUT2 _IO('V', (BASE_VIDIOC_PRIVATE + 5)) Loading