+++ /dev/null
-/*
- * 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); */
+++ /dev/null
-/*
- * 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
(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;
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 */
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);
}
}
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);