gfx: drv: DPST 3.0 kernel side support
authorAntti Koskipaa <antti.koskipaa@linux.intel.com>
Wed, 28 Mar 2012 11:25:53 +0000 (14:25 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:47 +0000 (12:30 +0300)
This patch removes the dead UMG workqueue implementation and adds support
for sending signals to userspace on DPST interrupts. The DRM fasync
infrastructure is used for this.

SIGIO/POLL_IN is sent on histogram interrupts and SIGIO/POLL_OUT on
phase-in interrupts.

Issue: ANDROID-2333
Signed-off-by: Antti Koskipaa <antti.koskipaa@linux.intel.com>
Signed-off-by: Yong-Joon.Park <yong-joon.park@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
(with a claim he does not know DPST)
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
drivers/staging/mrst/Makefile
drivers/staging/mrst/drv/psb_dpst.c [deleted file]
drivers/staging/mrst/drv/psb_dpst.h [deleted file]
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_drv.h
drivers/staging/mrst/drv/psb_irq.c
drivers/staging/mrst/imgv/psb_ttm_glue.c

index 66c76f2..530a340 100644 (file)
@@ -171,7 +171,6 @@ medfield_gfx-y += \
        $(DRMDRVDIR)/mdfld_output.o \
        $(DRMDRVDIR)/mdfld_overlay.o \
        $(DRMDRVDIR)/psb_bl.o \
-       $(DRMDRVDIR)/psb_dpst.o \
        $(DRMDRVDIR)/psb_drv.o \
        $(DRMDRVDIR)/psb_fb.o \
        $(DRMDRVDIR)/psb_gtt.o \
diff --git a/drivers/staging/mrst/drv/psb_dpst.c b/drivers/staging/mrst/drv/psb_dpst.c
deleted file mode 100644 (file)
index 7499b39..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *    James C. Gualario <james.c.gualario@intel.com>
- *
- */
-
-#include "psb_umevents.h"
-#include "psb_dpst.h"
-/**
- * inform the kernel of the work to be performed and related function.
- *
- */
-static DECLARE_WORK(dpst_dev_change_work, &psb_dpst_dev_change_wq);
-/**
- * psb_dpst_notify_change_um - notify user mode of hotplug changes
- *
- * @name: name of event to notify user mode of change to
- * @state: dpst state struct to get workqueue from
- *
- */
-int psb_dpst_notify_change_um(enum dpst_event_enum event,
-                             struct dpst_state *state)
-{
-       if (state == NULL)
-               return IRQ_HANDLED;
-
-       state->dpst_change_wq_data.dev_name_arry_rw_status
-               [state->dpst_change_wq_data.dev_name_write] =
-               DRM_DPST_READY_TO_READ;
-       state->dpst_change_wq_data.dpst_events
-               [state->dpst_change_wq_data.dev_name_write] =
-               event;
-       if (state->dpst_change_wq_data.dev_name_read_write_wrap_ack == 1)
-               state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
-       state->dpst_change_wq_data.dev_name_write++;
-       if (state->dpst_change_wq_data.dev_name_write ==
-          state->dpst_change_wq_data.dev_name_read) {
-               state->dpst_change_wq_data.dev_name_write--;
-               return IRQ_NONE;
-       }
-       if (state->dpst_change_wq_data.dev_name_write >
-          DRM_DPST_RING_DEPTH_MAX) {
-               state->dpst_change_wq_data.dev_name_write = 0;
-               state->dpst_change_wq_data.dev_name_write_wrap = 1;
-       }
-       state->dpst_change_wq_data.hotplug_dev_list = state->list;
-       queue_work(state->dpst_wq, &(state->dpst_change_wq_data.work));
-       return IRQ_HANDLED;
-}
-/*EXPORT_SYMBOL(psb_dpst_notify_change_um); */
-/**
- *
- * psb_dpst_create_and_notify_um - create and notify user mode of new dev
- *
- * @name: name to give for new event / device
- * @state: dpst state instaces to associate event with
- *
- */
-struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
-                                                 struct dpst_state *state)
-{
-       return psb_create_umevent_obj(name, state->list);
-
-}
-/*EXPORT_SYMBOL(psb_dpst_create_and_notify_um); */
-/**
- * psb_dpst_device_pool_create_and_init - make new hotplug device pool
- *
- * @parent_kobj - parent kobject to associate dpst kset with
- * @state - dpst state instance to associate list with
- *
- */
-struct umevent_list *psb_dpst_device_pool_create_and_init(
-                                                 struct kobject *parent_kobj,
-                                                 struct dpst_state *state)
-{
-       struct umevent_list *new_hotplug_dev_list = NULL;
-       new_hotplug_dev_list = psb_umevent_create_list();
-       if (new_hotplug_dev_list)
-               psb_umevent_init(parent_kobj, new_hotplug_dev_list,
-                                "psb_dpst");
-
-       state->dpst_wq = create_singlethread_workqueue("dpst-wq");
-
-       if (!state->dpst_wq)
-               return NULL;
-
-       INIT_WORK(&state->dpst_change_wq_data.work, psb_dpst_dev_change_wq);
-
-       state->dpst_change_wq_data.dev_name_read = 0;
-       state->dpst_change_wq_data.dev_name_write = 0;
-       state->dpst_change_wq_data.dev_name_write_wrap = 0;
-       state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
-
-       memset(&(state->dpst_change_wq_data.dev_name_arry_rw_status[0]),
-              0, sizeof(int)*DRM_DPST_RING_DEPTH);
-
-       return new_hotplug_dev_list;
-}
-/*EXPORT_SYMBOL(psb_dpst_device_pool_create_and_init);  */
-/**
- * psb_dpst_init - init dpst subsystem
- * @parent_kobj - parent kobject to associate dpst state with
- *
- */
-struct dpst_state *psb_dpst_init(struct kobject *parent_kobj)
-{
-       struct dpst_state *state;
-       struct umevent_obj *working_umevent;
-
-       state = kzalloc(sizeof(struct dpst_state), GFP_KERNEL);
-       state->list = NULL;
-       state->list = psb_dpst_device_pool_create_and_init(
-                                                 parent_kobj,
-                                                 state);
-       working_umevent  =
-               psb_dpst_create_and_notify_um("init",
-                                          state);
-       state->dpst_change_wq_data.dev_umevent_arry
-               [DPST_EVENT_INIT_COMPLETE] = &(working_umevent->head);
-       working_umevent  =
-               psb_dpst_create_and_notify_um("hist_int",
-                                          state);
-       state->dpst_change_wq_data.dev_umevent_arry
-               [DPST_EVENT_HIST_INTERRUPT] = &(working_umevent->head);
-       working_umevent  =
-               psb_dpst_create_and_notify_um("term",
-                                          state);
-       state->dpst_change_wq_data.dev_umevent_arry
-               [DPST_EVENT_TERMINATE] = &(working_umevent->head);
-       working_umevent  =
-               psb_dpst_create_and_notify_um("phase_done",
-                                          state);
-       state->dpst_change_wq_data.dev_umevent_arry
-               [DPST_EVENT_PHASE_COMPLETE] = &(working_umevent->head);
-
-       return state;
-}
-/*EXPORT_SYMBOL(psb_dpst_init); */
-/**
- * psb_dpst_device_pool_destroy - destroy all dpst related resources
- *
- * @state: dpst state instance to destroy
- *
- */
-void psb_dpst_device_pool_destroy(struct dpst_state *state)
-{
-       int i;
-       struct umevent_list *list;
-       struct umevent_obj *umevent_test;
-       list = state->list;
-       flush_workqueue(state->dpst_wq);
-       destroy_workqueue(state->dpst_wq);
-       for (i = 0; i < DRM_DPST_MAX_NUM_EVENTS;  i++) {
-               umevent_test = list_entry(
-                         (state->dpst_change_wq_data.dev_umevent_arry[i]),
-                         struct umevent_obj, head);
-               state->dpst_change_wq_data.dev_umevent_arry[i] = NULL;
-       }
-       psb_umevent_cleanup(list);
-       kfree(state);
-}
-/*EXPORT_SYMBOL(psb_dpst_device_pool_destroy); */
-/**
- * psb_dpst_dev_change_wq - change workqueue implementation
- *
- * @work: work struct to use for kernel scheduling
- *
- */
-void psb_dpst_dev_change_wq(struct work_struct *work)
-{
-       struct dpst_disp_workqueue_data *wq_data;
-       int curr_event_index;
-       wq_data = to_dpst_disp_workqueue_data(work);
-       if (wq_data->dev_name_write_wrap == 1) {
-               wq_data->dev_name_read_write_wrap_ack = 1;
-               wq_data->dev_name_write_wrap = 0;
-               while (wq_data->dev_name_read != DRM_DPST_RING_DEPTH_MAX) {
-                       if (wq_data->dev_name_arry_rw_status
-                          [wq_data->dev_name_read] ==
-                          DRM_DPST_READY_TO_READ) {
-                               wq_data->dev_name_arry_rw_status
-                               [wq_data->dev_name_read] =
-                               DRM_DPST_READ_COMPLETE;
-                               curr_event_index = wq_data->dpst_events
-                                       [wq_data->dev_name_read];
-                               psb_umevent_notify_change_gfxsock
-                                       (list_entry(
-                                          (wq_data->dev_umevent_arry
-                                           [curr_event_index]),
-                                          struct umevent_obj, head),
-                                        DRM_DPST_SOCKET_GROUP_ID);
-                       }
-                       wq_data->dev_name_read++;
-               }
-               wq_data->dev_name_read = 0;
-               while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
-                       if (wq_data->dev_name_arry_rw_status
-                          [wq_data->dev_name_read] ==
-                          DRM_DPST_READY_TO_READ) {
-                               wq_data->dev_name_arry_rw_status
-                               [wq_data->dev_name_read] =
-                               DRM_DPST_READ_COMPLETE;
-                               curr_event_index = wq_data->dpst_events
-                                       [wq_data->dev_name_read];
-                               psb_umevent_notify_change_gfxsock
-                                       (list_entry(
-                                          (wq_data->dev_umevent_arry
-                                           [curr_event_index]),
-                                          struct umevent_obj, head),
-                                        DRM_DPST_SOCKET_GROUP_ID);
-                       }
-                       wq_data->dev_name_read++;
-               }
-       } else {
-               while (wq_data->dev_name_read < wq_data->dev_name_write) {
-                       if (wq_data->dev_name_arry_rw_status
-                          [wq_data->dev_name_read] ==
-                          DRM_DPST_READY_TO_READ) {
-                               wq_data->dev_name_arry_rw_status
-                               [wq_data->dev_name_read] =
-                                       DRM_DPST_READ_COMPLETE;
-                               curr_event_index = wq_data->dpst_events
-                                       [wq_data->dev_name_read];
-                               psb_umevent_notify_change_gfxsock
-                                       (list_entry(
-                                          (wq_data->dev_umevent_arry
-                                           [curr_event_index]),
-                                          struct umevent_obj, head),
-                                        DRM_DPST_SOCKET_GROUP_ID);
-                       }
-                       wq_data->dev_name_read++;
-               }
-       }
-       if (wq_data->dev_name_read > DRM_DPST_RING_DEPTH_MAX)
-               wq_data->dev_name_read = 0;
-}
-/*EXPORT_SYMBOL(psb_dpst_dev_change_wq); */
diff --git a/drivers/staging/mrst/drv/psb_dpst.h b/drivers/staging/mrst/drv/psb_dpst.h
deleted file mode 100644 (file)
index 6f24a05..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- *    James C. Gualario <james.c.gualario@intel.com>
- *
- */
-
-#ifndef _PSB_DPST_H_
-#define _PSB_DPST_H_
-/**
- * required includes
- *
- */
-#include "psb_umevents.h"
-/**
- * dpst event enumeration
- *
- */
-enum dpst_event_enum {
-       DPST_EVENT_INIT_COMPLETE,
-       DPST_EVENT_HIST_INTERRUPT,
-       DPST_EVENT_TERMINATE,
-       DPST_EVENT_PHASE_COMPLETE,
-       DPST_MAX_EVENT
-};
-/**
- * dpst specific defines
- *
- */
-#define DRM_DPST_RING_DEPTH 256
-#define DRM_DPST_RING_DEPTH_MAX (DRM_DPST_RING_DEPTH-1)
-#define DRM_DPST_READY_TO_READ 1
-#define DRM_DPST_READ_COMPLETE 2
-#define DRM_DPST_MAX_NUM_EVENTS (DPST_MAX_EVENT)
-/**
- * dpst workqueue data struct.
- */
-struct dpst_disp_workqueue_data {
-       struct work_struct work;
-       const char *dev_name;
-       int dev_name_write;
-       int dev_name_read;
-       int dev_name_write_wrap;
-       int dev_name_read_write_wrap_ack;
-       enum dpst_event_enum dpst_events[DRM_DPST_RING_DEPTH];
-       int dev_name_arry_rw_status[DRM_DPST_RING_DEPTH];
-       struct umevent_list *hotplug_dev_list;
-       struct list_head *dev_umevent_arry[DRM_DPST_MAX_NUM_EVENTS];
-};
-/**
- * dpst state structure
- *
- */
-struct dpst_state {
-       struct workqueue_struct *dpst_wq;
-       struct dpst_disp_workqueue_data dpst_change_wq_data;
-       struct umevent_list *list;
-};
-/**
- * main interface function prototytpes for dpst support.
- *
- */
-extern struct dpst_state *psb_dpst_init(struct kobject *parent_kobj);
-extern int psb_dpst_notify_change_um(enum dpst_event_enum event,
-                                    struct dpst_state *state);
-extern struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
-                                                struct dpst_state *state);
-extern struct umevent_list *psb_dpst_device_pool_create_and_init(
-                                                struct kobject *parent_kobj,
-                                                struct dpst_state *state);
-extern void psb_dpst_device_pool_destroy(struct dpst_state *state);
-/**
- * to go back and forth between work struct and workqueue data
- *
- */
-#define to_dpst_disp_workqueue_data(x) \
-       container_of(x, struct dpst_disp_workqueue_data, work)
-
-/**
- * function prototypes for workqueue implementation
- *
- */
-extern void psb_dpst_dev_change_wq(struct work_struct *work);
-#endif
index e349b11..a65ff77 100644 (file)
@@ -1063,8 +1063,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
        dev_priv->num_pipe = 3;
 
-       /*init DPST umcomm to NULL*/
-       dev_priv->psb_dpst_state = NULL;
        dev_priv->psb_hotplug_state = NULL;
        dev_priv->hdmi_done_reading_edid = false;
        dev_priv->xserver_start = false;
@@ -1600,36 +1598,10 @@ static int psb_hist_status_ioctl(struct drm_device *dev, void *data,
 static int psb_init_comm_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file_priv)
 {
-       struct drm_psb_private *dev_priv = psb_priv(dev);
-       struct pci_dev *pdev = NULL;
-       struct device *ddev = NULL;
-       struct kobject *kobj = NULL;
-       uint32_t *arg = data;
-
-       if (*arg == 1) {
-               /*find handle to drm kboject*/
-               pdev = dev->pdev;
-               ddev = &pdev->dev;
-               kobj = &ddev->kobj;
-
-               if (dev_priv->psb_dpst_state == NULL) {
-                       /*init dpst kmum comms*/
-                       dev_priv->psb_dpst_state = psb_dpst_init(kobj);
-               } else {
-                       printk(KERN_ALERT "DPST already initialized\n");
-               }
-
+       if (*(int *)data == 1)
                psb_irq_enable_dpst(dev);
-               psb_dpst_notify_change_um(DPST_EVENT_INIT_COMPLETE,
-                                         dev_priv->psb_dpst_state);
-       } else {
-               /*hotplug and dpst destroy examples*/
+       else
                psb_irq_disable_dpst(dev);
-               psb_dpst_notify_change_um(DPST_EVENT_TERMINATE,
-                                         dev_priv->psb_dpst_state);
-               psb_dpst_device_pool_destroy(dev_priv->psb_dpst_state);
-               dev_priv->psb_dpst_state = NULL;
-       }
        return 0;
 }
 
index 8c9259b..328f8bf 100644 (file)
@@ -30,7 +30,6 @@
 #include "psb_schedule.h"
 #include "psb_intel_drv.h"
 #include "psb_hotplug.h"
-#include "psb_dpst.h"
 #include "psb_gtt.h"
 #include "psb_powermgmt.h"
 #include "ttm/ttm_object.h"
@@ -898,7 +897,6 @@ struct drm_psb_private {
         * DPST and Hotplug state
         */
 
-       struct dpst_state *psb_dpst_state;
        struct hotplug_state *psb_hotplug_state;
        pfn_vsync_handler psb_vsync_handler;
 
index 284f6f1..ee21cc2 100644 (file)
@@ -265,6 +265,7 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
                (struct drm_psb_private *) dev->dev_private;
 
        uint32_t pipe_stat_val = 0;
+       uint32_t pipe_stat_val_b = 0;
        uint32_t pipe_stat_reg = psb_pipestat(pipe);
        uint32_t pipe_enable = dev_priv->pipestat[pipe];
        uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
@@ -277,6 +278,8 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
        pipe_stat_val &= pipe_enable | pipe_status;
        pipe_stat_val &= pipe_stat_val >> 16;
 
+       pipe_stat_val_b = PSB_RVDC32(PSB_PIPESTAT(PSB_PIPE_B));
+
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irq_flags);
 
        /* clear the 2nd level interrupt status bits */
@@ -297,48 +300,28 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
                DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x. \n",
                          __FUNCTION__, PSB_RVDC32(pipe_stat_reg));
 
-       if ((pipe_stat_val & PIPE_DPST_EVENT_STATUS) &&
-           (dev_priv->psb_dpst_state != NULL)) {
+       if (pipe_stat_val_b & PIPE_DPST_EVENT_STATUS) {
                uint32_t pwm_reg = 0;
                uint32_t hist_reg = 0;
-               u32 irqCtrl = 0;
                struct dpst_guardband guardband_reg;
-               struct dpst_ie_histogram_control ie_hist_cont_reg;
-
                hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
 
                /* Determine if this is histogram or pwm interrupt */
                if (hist_reg & HISTOGRAM_INT_CTRL_CLEAR) {
-                       /* Notify UM of histogram interrupt */
-                       psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT,
-                                                 dev_priv->psb_dpst_state);
+                       /* Send a SIGIO with a band of POLL_IN on hist irq */
+                       kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
 
                        /* disable dpst interrupts */
                        guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
                        guardband_reg.interrupt_enable = 0;
                        guardband_reg.interrupt_status = 1;
                        PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
-
-                       ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
-                       ie_hist_cont_reg.ie_histogram_enable = 0;
-                       PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
-
-                       irqCtrl = PSB_RVDC32(PSB_PIPESTAT(PSB_PIPE_A));
-                       irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
-                       PSB_WVDC32(irqCtrl, PSB_PIPESTAT(PSB_PIPE_A));
                }
+               /* Send a SIGIO with a band of POLL_OUT on phase irq */
                pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
                if ((pwm_reg & PWM_PHASEIN_INT_ENABLE) &&
                    !(pwm_reg & PWM_PHASEIN_ENABLE)) {
-                       /* Notify UM of the phase complete */
-                       psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE,
-                                                 dev_priv->psb_dpst_state);
-
-                       /* Temporarily get phase mngr ready to generate
-                        * another interrupt until this can be moved to
-                        * user mode */
-                       /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
-                                  PWM_CONTROL_LOGIC); */
+                       kill_fasync(&dev->buf_async, SIGIO, POLL_OUT);
                }
        }
 
@@ -681,7 +664,7 @@ void psb_irq_turn_on_dpst(struct drm_device *dev)
        u32 hist_reg;
        u32 pwm_reg;
 
-       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false)) {
+       if (ospm_power_using_hw_begin_atomic(OSPM_DISPLAY_ISLAND)) {
                PSB_WVDC32(BIT(31), HISTOGRAM_LOGIC_CONTROL);
                hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
                PSB_WVDC32(BIT(31), HISTOGRAM_INT_CONTROL);
index e598b21..bc9c6f2 100644 (file)
@@ -107,6 +107,9 @@ int psb_release(struct inode *inode, struct file *filp)
 
        psb_cleanup_pending_events(dev, psb_fp);
 
+       /* Disable asynchronous notifications for the DRM file descriptor. */
+       drm_fasync(-1, filp, 0);
+
        /*cleanup for msvdx*/
        if (msvdx_priv->tfile == psb_fpriv(file_priv)->tfile) {
                msvdx_priv->fw_status = 0;