brintos

brintos / linux-shallow public Read only

0
0
Text · 21.4 KiB · 1e246b4 Raw
849 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Driver for the Auvitek USB bridge4 *5 *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>6 */7 8#include "au0828.h"9#include "au8522.h"10 11#include <linux/module.h>12#include <linux/slab.h>13#include <linux/videodev2.h>14#include <media/v4l2-common.h>15#include <linux/mutex.h>16 17/* Due to enum tuner_pad_index */18#include <media/tuner.h>19 20/*21 * 1 = General debug messages22 * 2 = USB handling23 * 4 = I2C related24 * 8 = Bridge related25 * 16 = IR related26 */27int au0828_debug;28module_param_named(debug, au0828_debug, int, 0644);29MODULE_PARM_DESC(debug,30		 "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");31 32static unsigned int disable_usb_speed_check;33module_param(disable_usb_speed_check, int, 0444);34MODULE_PARM_DESC(disable_usb_speed_check,35		 "override min bandwidth requirement of 480M bps");36 37#define _AU0828_BULKPIPE 0x0338#define _BULKPIPESIZE 0xffff39 40static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,41			    u16 index);42static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,43	u16 index, unsigned char *cp, u16 size);44 45/* USB Direction */46#define CMD_REQUEST_IN		0x0047#define CMD_REQUEST_OUT		0x0148 49u32 au0828_readreg(struct au0828_dev *dev, u16 reg)50{51	u8 result = 0;52 53	recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);54	dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);55 56	return result;57}58 59u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)60{61	dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);62	return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);63}64 65static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,66	u16 index)67{68	int status = -ENODEV;69 70	if (dev->usbdev) {71 72		/* cp must be memory that has been allocated by kmalloc */73		status = usb_control_msg(dev->usbdev,74				usb_sndctrlpipe(dev->usbdev, 0),75				request,76				USB_DIR_OUT | USB_TYPE_VENDOR |77					USB_RECIP_DEVICE,78				value, index, NULL, 0, 1000);79 80		status = min(status, 0);81 82		if (status < 0) {83			pr_err("%s() Failed sending control message, error %d.\n",84				__func__, status);85		}86 87	}88 89	return status;90}91 92static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,93	u16 index, unsigned char *cp, u16 size)94{95	int status = -ENODEV;96	mutex_lock(&dev->mutex);97	if (dev->usbdev) {98		status = usb_control_msg(dev->usbdev,99				usb_rcvctrlpipe(dev->usbdev, 0),100				request,101				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,102				value, index,103				dev->ctrlmsg, size, 1000);104 105		status = min(status, 0);106 107		if (status < 0) {108			pr_err("%s() Failed receiving control message, error %d.\n",109				__func__, status);110		}111 112		/* the host controller requires heap allocated memory, which113		   is why we didn't just pass "cp" into usb_control_msg */114		memcpy(cp, dev->ctrlmsg, size);115	}116	mutex_unlock(&dev->mutex);117	return status;118}119 120#ifdef CONFIG_MEDIA_CONTROLLER121static void au0828_media_graph_notify(struct media_entity *new,122				      void *notify_data);123#endif124 125static void au0828_unregister_media_device(struct au0828_dev *dev)126{127#ifdef CONFIG_MEDIA_CONTROLLER128	struct media_device *mdev = dev->media_dev;129	struct media_entity_notify *notify, *nextp;130 131	if (!mdev || !media_devnode_is_registered(mdev->devnode))132		return;133 134	/* Remove au0828 entity_notify callbacks */135	list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list) {136		if (notify->notify != au0828_media_graph_notify)137			continue;138		media_device_unregister_entity_notify(mdev, notify);139	}140 141	/* clear enable_source, disable_source */142	mutex_lock(&mdev->graph_mutex);143	dev->media_dev->source_priv = NULL;144	dev->media_dev->enable_source = NULL;145	dev->media_dev->disable_source = NULL;146	mutex_unlock(&mdev->graph_mutex);147 148	media_device_delete(dev->media_dev, KBUILD_MODNAME, THIS_MODULE);149	dev->media_dev = NULL;150#endif151}152 153void au0828_usb_release(struct au0828_dev *dev)154{155	au0828_unregister_media_device(dev);156 157	/* I2C */158	au0828_i2c_unregister(dev);159 160	kfree(dev);161}162 163static void au0828_usb_disconnect(struct usb_interface *interface)164{165	struct au0828_dev *dev = usb_get_intfdata(interface);166 167	dprintk(1, "%s()\n", __func__);168 169	/* there is a small window after disconnect, before170	   dev->usbdev is NULL, for poll (e.g: IR) try to access171	   the device and fill the dmesg with error messages.172	   Set the status so poll routines can check and avoid173	   access after disconnect.174	*/175	set_bit(DEV_DISCONNECTED, &dev->dev_state);176 177	au0828_rc_unregister(dev);178	/* Digital TV */179	au0828_dvb_unregister(dev);180 181	usb_set_intfdata(interface, NULL);182	mutex_lock(&dev->mutex);183	dev->usbdev = NULL;184	mutex_unlock(&dev->mutex);185	if (au0828_analog_unregister(dev)) {186		/*187		 * No need to call au0828_usb_release() if V4L2 is enabled,188		 * as this is already called via au0828_usb_v4l2_release()189		 */190		return;191	}192	au0828_usb_release(dev);193}194 195static int au0828_media_device_init(struct au0828_dev *dev,196				    struct usb_device *udev)197{198#ifdef CONFIG_MEDIA_CONTROLLER199	struct media_device *mdev;200 201	mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);202	if (IS_ERR(mdev))203		return PTR_ERR(mdev);204 205	dev->media_dev = mdev;206#endif207	return 0;208}209 210#ifdef CONFIG_MEDIA_CONTROLLER211static void au0828_media_graph_notify(struct media_entity *new,212				      void *notify_data)213{214	struct au0828_dev *dev = notify_data;215	int ret;216	struct media_entity *entity, *mixer = NULL, *decoder = NULL;217 218	if (!new) {219		/*220		 * Called during au0828 probe time to connect221		 * entities that were created prior to registering222		 * the notify handler. Find mixer and decoder.223		*/224		media_device_for_each_entity(entity, dev->media_dev) {225			if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)226				mixer = entity;227			else if (entity->function == MEDIA_ENT_F_ATV_DECODER)228				decoder = entity;229		}230		goto create_link;231	}232 233	switch (new->function) {234	case MEDIA_ENT_F_AUDIO_MIXER:235		mixer = new;236		if (dev->decoder)237			decoder = dev->decoder;238		break;239	case MEDIA_ENT_F_ATV_DECODER:240		/* In case, Mixer is added first, find mixer and create link */241		media_device_for_each_entity(entity, dev->media_dev) {242			if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)243				mixer = entity;244		}245		decoder = new;246		break;247	default:248		break;249	}250 251create_link:252	if (decoder && mixer) {253		ret = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,254					  PAD_SIGNAL_AUDIO);255		if (ret >= 0)256			ret = media_create_pad_link(decoder, ret,257						    mixer, 0,258						    MEDIA_LNK_FL_ENABLED);259		if (ret < 0)260			dev_err(&dev->usbdev->dev,261				"Mixer Pad Link Create Error: %d\n", ret);262	}263}264 265static bool au0828_is_link_shareable(struct media_entity *owner,266				     struct media_entity *entity)267{268	bool shareable = false;269 270	/* Tuner link can be shared by audio, video, and VBI */271	switch (owner->function) {272	case MEDIA_ENT_F_IO_V4L:273	case MEDIA_ENT_F_AUDIO_CAPTURE:274	case MEDIA_ENT_F_IO_VBI:275		if (entity->function == MEDIA_ENT_F_IO_V4L ||276		    entity->function == MEDIA_ENT_F_AUDIO_CAPTURE ||277		    entity->function == MEDIA_ENT_F_IO_VBI)278			shareable = true;279		break;280	case MEDIA_ENT_F_DTV_DEMOD:281	default:282		break;283	}284	return shareable;285}286 287/* Callers should hold graph_mutex */288static int au0828_enable_source(struct media_entity *entity,289				struct media_pipeline *pipe)290{291	struct media_entity  *source, *find_source;292	struct media_entity *sink;293	struct media_link *link, *found_link = NULL;294	int ret = 0;295	struct media_device *mdev = entity->graph_obj.mdev;296	struct au0828_dev *dev;297 298	if (!mdev)299		return -ENODEV;300 301	dev = mdev->source_priv;302 303	/*304	 * For Audio and V4L2 entity, find the link to which decoder305	 * is the sink. Look for an active link between decoder and306	 * source (tuner/s-video/Composite), if one exists, nothing307	 * to do. If not, look for any  active links between source308	 * and any other entity. If one exists, source is busy. If309	 * source is free, setup link and start pipeline from source.310	 * For DVB FE entity, the source for the link is the tuner.311	 * Check if tuner is available and setup link and start312	 * pipeline.313	*/314	if (entity->function == MEDIA_ENT_F_DTV_DEMOD) {315		sink = entity;316		find_source = dev->tuner;317	} else {318		/* Analog isn't configured or register failed */319		if (!dev->decoder) {320			ret = -ENODEV;321			goto end;322		}323 324		sink = dev->decoder;325 326		/*327		 * Default input is tuner and default input_type328		 * is AU0828_VMUX_TELEVISION.329		 *330		 * There is a problem when s_input is called to331		 * change the default input. s_input will try to332		 * enable_source before attempting to change the333		 * input on the device, and will end up enabling334		 * default source which is tuner.335		 *336		 * Additional logic is necessary in au0828 to detect337		 * that the input has changed and enable the right338		 * source. au0828 handles this case in its s_input.339		 * It will disable the old source and enable the new340		 * source.341		 *342		*/343		if (dev->input_type == AU0828_VMUX_TELEVISION)344			find_source = dev->tuner;345		else if (dev->input_type == AU0828_VMUX_SVIDEO ||346			 dev->input_type == AU0828_VMUX_COMPOSITE)347			find_source = &dev->input_ent[dev->input_type];348		else {349			/* unknown input - let user select input */350			ret = 0;351			goto end;352		}353	}354 355	/* Is there an active link between sink and source */356	if (dev->active_link) {357		if (dev->active_link_owner == entity) {358			/* This check is necessary to handle multiple359			 * enable_source calls from v4l_ioctls during360			 * the course of video/vbi application run-time.361			*/362			pr_debug("%s already owns the tuner\n", entity->name);363			ret = 0;364			goto end;365		} else if (au0828_is_link_shareable(dev->active_link_owner,366			   entity)) {367			/* Either ALSA or Video own tuner. Sink is the same368			 * for both. Allow sharing the active link between369			 * their common source (tuner) and sink (decoder).370			 * Starting pipeline between sharing entity and sink371			 * will fail with pipe mismatch, while owner has an372			 * active pipeline. Switch pipeline ownership from373			 * user to owner when owner disables the source.374			 */375			dev->active_link_shared = true;376			/* save the user info to use from disable */377			dev->active_link_user = entity;378			dev->active_link_user_pipe = pipe;379			pr_debug("%s owns the tuner %s can share!\n",380				 dev->active_link_owner->name,381				 entity->name);382			ret = 0;383			goto end;384		} else {385			ret = -EBUSY;386			goto end;387		}388	}389 390	list_for_each_entry(link, &sink->links, list) {391		/* Check sink, and source */392		if (link->sink->entity == sink &&393		    link->source->entity == find_source) {394			found_link = link;395			break;396		}397	}398 399	if (!found_link) {400		ret = -ENODEV;401		goto end;402	}403 404	/* activate link between source and sink and start pipeline */405	source = found_link->source->entity;406	ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);407	if (ret) {408		pr_err("Activate link from %s->%s. Error %d\n",409			source->name, sink->name, ret);410		goto end;411	}412 413	ret = __media_pipeline_start(entity->pads, pipe);414	if (ret) {415		pr_err("Start Pipeline: %s->%s Error %d\n",416			source->name, entity->name, ret);417		ret = __media_entity_setup_link(found_link, 0);418		if (ret)419			pr_err("Deactivate link Error %d\n", ret);420		goto end;421	}422 423	/* save link state to allow audio and video share the link424	 * and not disable the link while the other is using it.425	 * active_link_owner is used to deactivate the link.426	*/427	dev->active_link = found_link;428	dev->active_link_owner = entity;429	dev->active_source = source;430	dev->active_sink = sink;431 432	pr_info("Enabled Source: %s->%s->%s Ret %d\n",433		 dev->active_source->name, dev->active_sink->name,434		 dev->active_link_owner->name, ret);435end:436	pr_debug("%s end: ent:%s fnc:%d ret %d\n",437		 __func__, entity->name, entity->function, ret);438	return ret;439}440 441/* Callers should hold graph_mutex */442static void au0828_disable_source(struct media_entity *entity)443{444	int ret = 0;445	struct media_device *mdev = entity->graph_obj.mdev;446	struct au0828_dev *dev;447 448	if (!mdev)449		return;450 451	dev = mdev->source_priv;452 453	if (!dev->active_link)454		return;455 456	/* link is active - stop pipeline from source457	 * (tuner/s-video/Composite) to the entity458	 * When DVB/s-video/Composite owns tuner, it won't be in459	 * shared state.460	 */461	if (dev->active_link->sink->entity == dev->active_sink &&462	    dev->active_link->source->entity == dev->active_source) {463		/*464		 * Prevent video from deactivating link when audio465		 * has active pipeline and vice versa. In addition466		 * handle the case when more than one video/vbi467		 * application is sharing the link.468		*/469		bool owner_is_audio = false;470 471		if (dev->active_link_owner->function ==472		    MEDIA_ENT_F_AUDIO_CAPTURE)473			owner_is_audio = true;474 475		if (dev->active_link_shared) {476			pr_debug("Shared link owner %s user %s %d\n",477				 dev->active_link_owner->name,478				 entity->name, dev->users);479 480			/* Handle video device users > 1481			 * When audio owns the shared link with482			 * more than one video users, avoid483			 * disabling the source and/or switching484			 * the owner until the last disable_source485			 * call from video _close(). Use dev->users to486			 * determine when to switch/disable.487			 */488			if (dev->active_link_owner != entity) {489				/* video device has users > 1 */490				if (owner_is_audio && dev->users > 1)491					return;492 493				dev->active_link_user = NULL;494				dev->active_link_user_pipe = NULL;495				dev->active_link_shared = false;496				return;497			}498 499			/* video owns the link and has users > 1 */500			if (!owner_is_audio && dev->users > 1)501				return;502 503			/* stop pipeline */504			__media_pipeline_stop(dev->active_link_owner->pads);505			pr_debug("Pipeline stop for %s\n",506				dev->active_link_owner->name);507 508			ret = __media_pipeline_start(509					dev->active_link_user->pads,510					dev->active_link_user_pipe);511			if (ret) {512				pr_err("Start Pipeline: %s->%s %d\n",513					dev->active_source->name,514					dev->active_link_user->name,515					ret);516				goto deactivate_link;517			}518			/* link user is now the owner */519			dev->active_link_owner = dev->active_link_user;520			dev->active_link_user = NULL;521			dev->active_link_user_pipe = NULL;522			dev->active_link_shared = false;523 524			pr_debug("Pipeline started for %s\n",525				dev->active_link_owner->name);526			return;527		} else if (!owner_is_audio && dev->users > 1)528			/* video/vbi owns the link and has users > 1 */529			return;530 531		if (dev->active_link_owner != entity)532			return;533 534		/* stop pipeline */535		__media_pipeline_stop(dev->active_link_owner->pads);536		pr_debug("Pipeline stop for %s\n",537			dev->active_link_owner->name);538 539deactivate_link:540		ret = __media_entity_setup_link(dev->active_link, 0);541		if (ret)542			pr_err("Deactivate link Error %d\n", ret);543 544		pr_info("Disabled Source: %s->%s->%s Ret %d\n",545			 dev->active_source->name, dev->active_sink->name,546			 dev->active_link_owner->name, ret);547 548		dev->active_link = NULL;549		dev->active_link_owner = NULL;550		dev->active_source = NULL;551		dev->active_sink = NULL;552		dev->active_link_shared = false;553		dev->active_link_user = NULL;554	}555}556#endif557 558static int au0828_media_device_register(struct au0828_dev *dev,559					struct usb_device *udev)560{561#ifdef CONFIG_MEDIA_CONTROLLER562	int ret;563	struct media_entity *entity, *demod = NULL;564	struct media_link *link;565 566	if (!dev->media_dev)567		return 0;568 569	if (!media_devnode_is_registered(dev->media_dev->devnode)) {570 571		/* register media device */572		ret = media_device_register(dev->media_dev);573		if (ret) {574			media_device_delete(dev->media_dev, KBUILD_MODNAME,575					    THIS_MODULE);576			dev->media_dev = NULL;577			dev_err(&udev->dev,578				"Media Device Register Error: %d\n", ret);579			return ret;580		}581	} else {582		/*583		 * Call au0828_media_graph_notify() to connect584		 * audio graph to our graph. In this case, audio585		 * driver registered the device and there is no586		 * entity_notify to be called when new entities587		 * are added. Invoke it now.588		*/589		au0828_media_graph_notify(NULL, (void *) dev);590	}591 592	/*593	 * Find tuner, decoder and demod.594	 *595	 * The tuner and decoder should be cached, as they'll be used by596	 *	au0828_enable_source.597	 *598	 * It also needs to disable the link between tuner and599	 * decoder/demod, to avoid disable step when tuner is requested600	 * by video or audio. Note that this step can't be done until dvb601	 * graph is created during dvb register.602	*/603	media_device_for_each_entity(entity, dev->media_dev) {604		switch (entity->function) {605		case MEDIA_ENT_F_TUNER:606			dev->tuner = entity;607			break;608		case MEDIA_ENT_F_ATV_DECODER:609			dev->decoder = entity;610			break;611		case MEDIA_ENT_F_DTV_DEMOD:612			demod = entity;613			break;614		}615	}616 617	/* Disable link between tuner->demod and/or tuner->decoder */618	if (dev->tuner) {619		list_for_each_entry(link, &dev->tuner->links, list) {620			if (demod && link->sink->entity == demod)621				media_entity_setup_link(link, 0);622			if (dev->decoder && link->sink->entity == dev->decoder)623				media_entity_setup_link(link, 0);624		}625	}626 627	/* register entity_notify callback */628	dev->entity_notify.notify_data = (void *) dev;629	dev->entity_notify.notify = (void *) au0828_media_graph_notify;630	media_device_register_entity_notify(dev->media_dev,631						  &dev->entity_notify);632 633	/* set enable_source */634	mutex_lock(&dev->media_dev->graph_mutex);635	dev->media_dev->source_priv = (void *) dev;636	dev->media_dev->enable_source = au0828_enable_source;637	dev->media_dev->disable_source = au0828_disable_source;638	mutex_unlock(&dev->media_dev->graph_mutex);639#endif640	return 0;641}642 643static int au0828_usb_probe(struct usb_interface *interface,644	const struct usb_device_id *id)645{646	int ifnum;647	int retval = 0;648 649	struct au0828_dev *dev;650	struct usb_device *usbdev = interface_to_usbdev(interface);651 652	ifnum = interface->altsetting->desc.bInterfaceNumber;653 654	if (ifnum != 0)655		return -ENODEV;656 657	dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,658		le16_to_cpu(usbdev->descriptor.idVendor),659		le16_to_cpu(usbdev->descriptor.idProduct),660		ifnum);661 662	/*663	 * Make sure we have 480 Mbps of bandwidth, otherwise things like664	 * video stream wouldn't likely work, since 12 Mbps is generally665	 * not enough even for most Digital TV streams.666	 */667	if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {668		pr_err("au0828: Device initialization failed.\n");669		pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");670		return -ENODEV;671	}672 673	dev = kzalloc(sizeof(*dev), GFP_KERNEL);674	if (dev == NULL) {675		pr_err("%s() Unable to allocate memory\n", __func__);676		return -ENOMEM;677	}678 679	mutex_init(&dev->lock);680	mutex_lock(&dev->lock);681	mutex_init(&dev->mutex);682	mutex_init(&dev->dvb.lock);683	dev->usbdev = usbdev;684	dev->boardnr = id->driver_info;685	dev->board = au0828_boards[dev->boardnr];686 687	/* Initialize the media controller */688	retval = au0828_media_device_init(dev, usbdev);689	if (retval) {690		pr_err("%s() au0828_media_device_init failed\n",691		       __func__);692		mutex_unlock(&dev->lock);693		kfree(dev);694		return retval;695	}696 697	retval = au0828_v4l2_device_register(interface, dev);698	if (retval) {699		au0828_usb_v4l2_media_release(dev);700		mutex_unlock(&dev->lock);701		kfree(dev);702		return retval;703	}704 705	/* Power Up the bridge */706	au0828_write(dev, REG_600, 1 << 4);707 708	/* Bring up the GPIO's and supporting devices */709	au0828_gpio_setup(dev);710 711	/* I2C */712	au0828_i2c_register(dev);713 714	/* Setup */715	au0828_card_setup(dev);716 717	/*718	 * Store the pointer to the au0828_dev so it can be accessed in719	 * au0828_usb_disconnect720	 */721	usb_set_intfdata(interface, dev);722 723	/* Analog TV */724	retval = au0828_analog_register(dev, interface);725	if (retval) {726		pr_err("%s() au0828_analog_register failed to register on V4L2\n",727			__func__);728		mutex_unlock(&dev->lock);729		goto done;730	}731 732	/* Digital TV */733	retval = au0828_dvb_register(dev);734	if (retval)735		pr_err("%s() au0828_dvb_register failed\n",736		       __func__);737 738	/* Remote controller */739	au0828_rc_register(dev);740 741	pr_info("Registered device AU0828 [%s]\n",742		dev->board.name == NULL ? "Unset" : dev->board.name);743 744	mutex_unlock(&dev->lock);745 746	retval = au0828_media_device_register(dev, usbdev);747 748done:749	if (retval < 0)750		au0828_usb_disconnect(interface);751 752	return retval;753}754 755static int au0828_suspend(struct usb_interface *interface,756				pm_message_t message)757{758	struct au0828_dev *dev = usb_get_intfdata(interface);759 760	if (!dev)761		return 0;762 763	pr_info("Suspend\n");764 765	au0828_rc_suspend(dev);766	au0828_v4l2_suspend(dev);767	au0828_dvb_suspend(dev);768 769	/* FIXME: should suspend also ATV/DTV */770 771	return 0;772}773 774static int au0828_resume(struct usb_interface *interface)775{776	struct au0828_dev *dev = usb_get_intfdata(interface);777	if (!dev)778		return 0;779 780	pr_info("Resume\n");781 782	/* Power Up the bridge */783	au0828_write(dev, REG_600, 1 << 4);784 785	/* Bring up the GPIO's and supporting devices */786	au0828_gpio_setup(dev);787 788	au0828_rc_resume(dev);789	au0828_v4l2_resume(dev);790	au0828_dvb_resume(dev);791 792	/* FIXME: should resume also ATV/DTV */793 794	return 0;795}796 797static struct usb_driver au0828_usb_driver = {798	.name		= KBUILD_MODNAME,799	.probe		= au0828_usb_probe,800	.disconnect	= au0828_usb_disconnect,801	.id_table	= au0828_usb_id_table,802	.suspend	= au0828_suspend,803	.resume		= au0828_resume,804	.reset_resume	= au0828_resume,805};806 807static int __init au0828_init(void)808{809	int ret;810 811	if (au0828_debug & 1)812		pr_info("%s() Debugging is enabled\n", __func__);813 814	if (au0828_debug & 2)815		pr_info("%s() USB Debugging is enabled\n", __func__);816 817	if (au0828_debug & 4)818		pr_info("%s() I2C Debugging is enabled\n", __func__);819 820	if (au0828_debug & 8)821		pr_info("%s() Bridge Debugging is enabled\n",822		       __func__);823 824	if (au0828_debug & 16)825		pr_info("%s() IR Debugging is enabled\n",826		       __func__);827 828	pr_info("au0828 driver loaded\n");829 830	ret = usb_register(&au0828_usb_driver);831	if (ret)832		pr_err("usb_register failed, error = %d\n", ret);833 834	return ret;835}836 837static void __exit au0828_exit(void)838{839	usb_deregister(&au0828_usb_driver);840}841 842module_init(au0828_init);843module_exit(au0828_exit);844 845MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");846MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");847MODULE_LICENSE("GPL");848MODULE_VERSION("0.0.3");849