1/* 2 * output.c - Display Output Switch driver 3 * 4 * Copyright (C) 2006 Luming Yu <luming.yu@intel.com> 5 * 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or (at 11 * your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 21 * 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 */ 24#include <linux/module.h> 25#include <linux/video_output.h> 26#include <linux/slab.h> 27#include <linux/err.h> 28#include <linux/ctype.h> 29 30 31MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction"); 32MODULE_LICENSE("GPL"); 33MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>"); 34 35static ssize_t video_output_show_state(struct device *dev, 36 struct device_attribute *attr, char *buf) 37{ 38 ssize_t ret_size = 0; 39 struct output_device *od = to_output_device(dev); 40 if (od->props) 41 ret_size = sprintf(buf,"%.8x\n",od->props->get_status(od)); 42 return ret_size; 43} 44 45static ssize_t video_output_store_state(struct device *dev, 46 struct device_attribute *attr, 47 const char *buf,size_t count) 48{ 49 char *endp; 50 struct output_device *od = to_output_device(dev); 51 int request_state = simple_strtoul(buf,&endp,0); 52 size_t size = endp - buf; 53 54 if (isspace(*endp)) 55 size++; 56 if (size != count) 57 return -EINVAL; 58 59 if (od->props) { 60 od->request_state = request_state; 61 od->props->set_state(od); 62 } 63 return count; 64} 65 66static void video_output_release(struct device *dev) 67{ 68 struct output_device *od = to_output_device(dev); 69 kfree(od); 70} 71 72static struct device_attribute video_output_attributes[] = { 73 __ATTR(state, 0644, video_output_show_state, video_output_store_state), 74 __ATTR_NULL, 75}; 76 77 78static struct class video_output_class = { 79 .name = "video_output", 80 .dev_release = video_output_release, 81 .dev_attrs = video_output_attributes, 82}; 83 84struct output_device *video_output_register(const char *name, 85 struct device *dev, 86 void *devdata, 87 struct output_properties *op) 88{ 89 struct output_device *new_dev; 90 int ret_code = 0; 91 92 new_dev = kzalloc(sizeof(struct output_device),GFP_KERNEL); 93 if (!new_dev) { 94 ret_code = -ENOMEM; 95 goto error_return; 96 } 97 new_dev->props = op; 98 new_dev->dev.class = &video_output_class; 99 new_dev->dev.parent = dev; 100 dev_set_name(&new_dev->dev, name); 101 dev_set_drvdata(&new_dev->dev, devdata); 102 ret_code = device_register(&new_dev->dev); 103 if (ret_code) { 104 kfree(new_dev); 105 goto error_return; 106 } 107 return new_dev; 108 109error_return: 110 return ERR_PTR(ret_code); 111} 112EXPORT_SYMBOL(video_output_register); 113 114void video_output_unregister(struct output_device *dev) 115{ 116 if (!dev) 117 return; 118 device_unregister(&dev->dev); 119} 120EXPORT_SYMBOL(video_output_unregister); 121 122static void __exit video_output_class_exit(void) 123{ 124 class_unregister(&video_output_class); 125} 126 127static int __init video_output_class_init(void) 128{ 129 return class_register(&video_output_class); 130} 131 132postcore_initcall(video_output_class_init); 133module_exit(video_output_class_exit); 134