diff options
57 files changed, 7206 insertions, 2412 deletions
diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt new file mode 100644 index 000000000000..07654f0338b6 --- /dev/null +++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt @@ -0,0 +1,41 @@ +Freescale i.MX IPUv3 +==================== + +Required properties: +- compatible: Should be "fsl,<chip>-ipu" +- reg: should be register base and length as documented in the + datasheet +- interrupts: Should contain sync interrupt and error interrupt, + in this order. +- #crtc-cells: 1, See below + +example: + +ipu: ipu@18000000 { + #crtc-cells = <1>; + compatible = "fsl,imx53-ipu"; + reg = <0x18000000 0x080000000>; + interrupts = <11 10>; +}; + +Parallel display support +======================== + +Required properties: +- compatible: Should be "fsl,imx-parallel-display" +- crtc: the crtc this display is connected to, see below +Optional properties: +- interface_pix_fmt: How this display is connected to the + crtc. Currently supported types: "rgb24", "rgb565" +- edid: verbatim EDID data block describing attached display. +- ddc: phandle describing the i2c bus handling the display data + channel + +example: + +display@di0 { + compatible = "fsl,imx-parallel-display"; + edid = [edid-data]; + crtc = <&ipu 0>; + interface-pix-fmt = "rgb24"; +}; diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 025d8c98424a..0f51a158ef70 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -140,4 +140,6 @@ source "drivers/staging/silicom/Kconfig" source "drivers/staging/ced1401/Kconfig" +source "drivers/staging/imx-drm/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 08e9667a4e45..f4b2bc41f1d1 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal/ obj-$(CONFIG_ZCACHE2) += ramster/ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ obj-$(CONFIG_CED1401) += ced1401/ +obj-$(CONFIG_DRM_IMX) += imx-drm/ diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index b6c20a92cbf8..25aa20aad65e 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -1913,7 +1913,7 @@ int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter, PUINT puiBuffer) { B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1)); - stIM_SFHostNotify *pHostInfo = NULL; + struct bcm_stim_sfhostnotify *pHostInfo = NULL; UINT uiSearchRuleIndex = 0; ULONG ulSFID = 0; @@ -1922,7 +1922,7 @@ VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter, PUINT puiBuffer while (u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) { u32NumofSFsinMsg--; - pHostInfo = (stIM_SFHostNotify *)puiBuffer; + pHostInfo = (struct bcm_stim_sfhostnotify *)puiBuffer; puiBuffer = (PUINT)(pHostInfo + 1); ulSFID = ntohl(pHostInfo->SFID); diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h index 41d732d8ca42..11b3181d537a 100644 --- a/drivers/staging/bcm/cntrl_SignalingInterface.h +++ b/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -1,423 +1,353 @@ #ifndef CNTRL_SIGNALING_INTERFACE_ #define CNTRL_SIGNALING_INTERFACE_ - - - -#define DSA_REQ 11 -#define DSA_RSP 12 -#define DSA_ACK 13 -#define DSC_REQ 14 -#define DSC_RSP 15 -#define DSC_ACK 16 -#define DSD_REQ 17 -#define DSD_RSP 18 -#define DSD_ACK 19 -#define MAX_CLASSIFIERS_IN_SF 4 - - -#define MAX_STRING_LEN 20 -#define MAX_PHS_LENGTHS 255 -#define VENDOR_PHS_PARAM_LENGTH 10 -#define MAX_NUM_ACTIVE_BS 10 -#define AUTH_TOKEN_LENGTH 10 -#define NUM_HARQ_CHANNELS 16 //Changed from 10 to 16 to accommodate all HARQ channels -#define VENDOR_CLASSIFIER_PARAM_LENGTH 1 //Changed the size to 1 byte since we dnt use it -#define VENDOR_SPECIF_QOS_PARAM 1 -#define VENDOR_PHS_PARAM_LENGTH 10 -#define MBS_CONTENTS_ID_LENGTH 10 -#define GLOBAL_SF_CLASSNAME_LENGTH 6 - -#define TYPE_OF_SERVICE_LENGTH 3 -#define IP_MASKED_SRC_ADDRESS_LENGTH 32 -#define IP_MASKED_DEST_ADDRESS_LENGTH 32 -#define PROTOCOL_SRC_PORT_RANGE_LENGTH 4 -#define PROTOCOL_DEST_PORT_RANGE_LENGTH 4 -#define ETHERNET_DEST_MAC_ADDR_LENGTH 12 -#define ETHERNET_SRC_MAC_ADDR_LENGTH 12 -#define NUM_ETHERTYPE_BYTES 3 -#define NUM_IPV6_FLOWLABLE_BYTES 3 - - -//////////////////////////////////////////////////////////////////////////////// -////////////////////////structure Definitions/////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// \brief class cCPacketClassificationRule -struct _stCPacketClassificationRuleSI{ - - /** 16bit UserPriority Of The Service Flow*/ - B_UINT16 u16UserPriority; - /** 16bit VLANID Of The Service Flow*/ - B_UINT16 u16VLANID; - /** 16bit Packet Classification RuleIndex Of The Service Flow*/ - B_UINT16 u16PacketClassificationRuleIndex; - /** 8bit Classifier Rule Priority Of The Service Flow*/ - B_UINT8 u8ClassifierRulePriority; - /** Length of IP TypeOfService field*/ - B_UINT8 u8IPTypeOfServiceLength; - /** 3bytes IP TypeOfService */ - B_UINT8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH]; - /** Protocol used in classification of Service Flow*/ - B_UINT8 u8Protocol; - /** Length of IP Masked Source Address */ - B_UINT8 u8IPMaskedSourceAddressLength; - /** IP Masked Source Address used in classification for the Service Flow*/ - B_UINT8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH]; - /** Length of IP Destination Address */ - B_UINT8 u8IPDestinationAddressLength; - /** IP Destination Address used in classification for the Service Flow*/ - B_UINT8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH]; - /** Length of Protocol Source Port Range */ - B_UINT8 u8ProtocolSourcePortRangeLength; - /** Protocol Source Port Range used in the Service Flow*/ - B_UINT8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH]; - /** Length of Protocol Dest Port Range */ - B_UINT8 u8ProtocolDestPortRangeLength; - /** Protocol Dest Port Range used in the Service Flow*/ - B_UINT8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH]; - /** Length of Ethernet Destination MAC Address */ - B_UINT8 u8EthernetDestMacAddressLength; - /** Ethernet Destination MAC Address used in classification of the Service Flow*/ - B_UINT8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH]; - /** Length of Ethernet Source MAC Address */ - B_UINT8 u8EthernetSourceMACAddressLength; - /** Ethernet Source MAC Address used in classification of the Service Flow*/ - B_UINT8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH]; - /** Length of Ethertype */ - B_UINT8 u8EthertypeLength; - /** 3bytes Ethertype Of The Service Flow*/ - B_UINT8 u8Ethertype[NUM_ETHERTYPE_BYTES]; - /** 8bit Associated PHSI Of The Service Flow*/ - B_UINT8 u8AssociatedPHSI; - /** Length of Vendor Specific Classifier Param length Of The Service Flow*/ - B_UINT8 u8VendorSpecificClassifierParamLength; - /** Vendor Specific Classifier Param Of The Service Flow*/ - B_UINT8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH]; - /** Length Of IPv6 Flow Lable of the Service Flow*/ - B_UINT8 u8IPv6FlowLableLength; - /** IPv6 Flow Lable Of The Service Flow*/ - B_UINT8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES]; - /** Action associated with the classifier rule*/ - B_UINT8 u8ClassifierActionRule; - B_UINT16 u16ValidityBitMap; +#define DSA_REQ 11 +#define DSA_RSP 12 +#define DSA_ACK 13 +#define DSC_REQ 14 +#define DSC_RSP 15 +#define DSC_ACK 16 +#define DSD_REQ 17 +#define DSD_RSP 18 +#define DSD_ACK 19 +#define MAX_CLASSIFIERS_IN_SF 4 + +#define MAX_STRING_LEN 20 +#define MAX_PHS_LENGTHS 255 +#define VENDOR_PHS_PARAM_LENGTH 10 +#define MAX_NUM_ACTIVE_BS 10 +#define AUTH_TOKEN_LENGTH 10 +#define NUM_HARQ_CHANNELS 16 /* Changed from 10 to 16 to accommodate all HARQ channels */ +#define VENDOR_CLASSIFIER_PARAM_LENGTH 1 /* Changed the size to 1 byte since we dnt use it */ +#define VENDOR_SPECIF_QOS_PARAM 1 +#define VENDOR_PHS_PARAM_LENGTH 10 +#define MBS_CONTENTS_ID_LENGTH 10 +#define GLOBAL_SF_CLASSNAME_LENGTH 6 + +#define TYPE_OF_SERVICE_LENGTH 3 +#define IP_MASKED_SRC_ADDRESS_LENGTH 32 +#define IP_MASKED_DEST_ADDRESS_LENGTH 32 +#define PROTOCOL_SRC_PORT_RANGE_LENGTH 4 +#define PROTOCOL_DEST_PORT_RANGE_LENGTH 4 +#define ETHERNET_DEST_MAC_ADDR_LENGTH 12 +#define ETHERNET_SRC_MAC_ADDR_LENGTH 12 +#define NUM_ETHERTYPE_BYTES 3 +#define NUM_IPV6_FLOWLABLE_BYTES 3 + +/* + * structure Definitions + * + * brief class cCPacketClassificationRule + */ +struct _stCPacketClassificationRuleSI { + /* 16bit UserPriority Of The Service Flow */ + B_UINT16 u16UserPriority; + /* 16bit VLANID Of The Service Flow */ + B_UINT16 u16VLANID; + /* 16bit Packet Classification RuleIndex Of The Service Flow */ + B_UINT16 u16PacketClassificationRuleIndex; + /* 8bit Classifier Rule Priority Of The Service Flow */ + B_UINT8 u8ClassifierRulePriority; + /* Length of IP TypeOfService field */ + B_UINT8 u8IPTypeOfServiceLength; + /* 3bytes IP TypeOfService */ + B_UINT8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH]; + /* Protocol used in classification of Service Flow */ + B_UINT8 u8Protocol; + /* Length of IP Masked Source Address */ + B_UINT8 u8IPMaskedSourceAddressLength; + /* IP Masked Source Address used in classification for the Service Flow */ + B_UINT8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH]; + /* Length of IP Destination Address */ + B_UINT8 u8IPDestinationAddressLength; + /* IP Destination Address used in classification for the Service Flow */ + B_UINT8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH]; + /* Length of Protocol Source Port Range */ + B_UINT8 u8ProtocolSourcePortRangeLength; + /* Protocol Source Port Range used in the Service Flow */ + B_UINT8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH]; + /* Length of Protocol Dest Port Range */ + B_UINT8 u8ProtocolDestPortRangeLength; + /* Protocol Dest Port Range used in the Service Flow */ + B_UINT8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH]; + /* Length of Ethernet Destination MAC Address */ + B_UINT8 u8EthernetDestMacAddressLength; + /* Ethernet Destination MAC Address used in classification of the Service Flow */ + B_UINT8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH]; + /* Length of Ethernet Source MAC Address */ + B_UINT8 u8EthernetSourceMACAddressLength; + /* Ethernet Source MAC Address used in classification of the Service Flow */ + B_UINT8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH]; + /* Length of Ethertype */ + B_UINT8 u8EthertypeLength; + /* 3bytes Ethertype Of The Service Flow */ + B_UINT8 u8Ethertype[NUM_ETHERTYPE_BYTES]; + /* 8bit Associated PHSI Of The Service Flow */ + B_UINT8 u8AssociatedPHSI; + /* Length of Vendor Specific Classifier Param length Of The Service Flow */ + B_UINT8 u8VendorSpecificClassifierParamLength; + /* Vendor Specific Classifier Param Of The Service Flow */ + B_UINT8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH]; + /* Length Of IPv6 Flow Lable of the Service Flow */ + B_UINT8 u8IPv6FlowLableLength; + /* IPv6 Flow Lable Of The Service Flow */ + B_UINT8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES]; + /* Action associated with the classifier rule */ + B_UINT8 u8ClassifierActionRule; + B_UINT16 u16ValidityBitMap; }; -typedef struct _stCPacketClassificationRuleSI CCPacketClassificationRuleSI,stCPacketClassificationRuleSI, *pstCPacketClassificationRuleSI; +typedef struct _stCPacketClassificationRuleSI CCPacketClassificationRuleSI, stCPacketClassificationRuleSI, *pstCPacketClassificationRuleSI; -/// \brief class CPhsRuleSI +/* brief class CPhsRuleSI */ typedef struct _stPhsRuleSI { - /** 8bit PHS Index Of The Service Flow*/ - B_UINT8 u8PHSI; - /** PHSF Length Of The Service Flow*/ - B_UINT8 u8PHSFLength; - /** String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS*/ - B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; - /** PHSM Length Of The Service Flow*/ - B_UINT8 u8PHSMLength; - /** PHS Mask for the SF*/ - B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; - /** 8bit Total number of bytes to be suppressed for the Service Flow*/ - B_UINT8 u8PHSS; - /** 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */ - B_UINT8 u8PHSV; - /** Vendor Specific PHS param Length Of The Service Flow*/ - B_UINT8 u8VendorSpecificPHSParamsLength; - /** Vendor Specific PHS param Of The Service Flow*/ - B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH]; - - B_UINT8 u8Padding[2]; -}stPhsRuleSI,*pstPhsRuleSI; + /* 8bit PHS Index Of The Service Flow */ + B_UINT8 u8PHSI; + /* PHSF Length Of The Service Flow */ + B_UINT8 u8PHSFLength; + /* String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS */ + B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; + /* PHSM Length Of The Service Flow */ + B_UINT8 u8PHSMLength; + /* PHS Mask for the SF */ + B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; + /* 8bit Total number of bytes to be suppressed for the Service Flow */ + B_UINT8 u8PHSS; + /* 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */ + B_UINT8 u8PHSV; + /* Vendor Specific PHS param Length Of The Service Flow */ + B_UINT8 u8VendorSpecificPHSParamsLength; + /* Vendor Specific PHS param Of The Service Flow */ + B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH]; + B_UINT8 u8Padding[2]; +} stPhsRuleSI, *pstPhsRuleSI; typedef stPhsRuleSI CPhsRuleSI; -/// \brief structure cConvergenceSLTypes -struct _stConvergenceSLTypes{ - /** 8bit Phs Classfier Action Of The Service Flow*/ - B_UINT8 u8ClassfierDSCAction; - /** 8bit Phs DSC Action Of The Service Flow*/ - B_UINT8 u8PhsDSCAction; - /** 16bit Padding */ - B_UINT8 u8Padding[2]; - /// \brief class cCPacketClassificationRule - stCPacketClassificationRuleSI cCPacketClassificationRule; - /// \brief class CPhsRuleSI - struct _stPhsRuleSI cPhsRule; +/* brief structure cConvergenceSLTypes */ +struct _stConvergenceSLTypes { + /* 8bit Phs Classfier Action Of The Service Flow */ + B_UINT8 u8ClassfierDSCAction; + /* 8bit Phs DSC Action Of The Service Flow */ + B_UINT8 u8PhsDSCAction; + /* 16bit Padding */ + B_UINT8 u8Padding[2]; + /* brief class cCPacketClassificationRule */ + stCPacketClassificationRuleSI cCPacketClassificationRule; + /* brief class CPhsRuleSI */ + struct _stPhsRuleSI cPhsRule; }; -typedef struct _stConvergenceSLTypes stConvergenceSLTypes,CConvergenceSLTypes, *pstConvergenceSLTypes; - - -/// \brief structure CServiceFlowParamSI -typedef struct _stServiceFlowParamSI{ - - /** 32bitSFID Of The Service Flow*/ - B_UINT32 u32SFID; - - /** 32bit Maximum Sustained Traffic Rate of the Service Flow*/ - B_UINT32 u32MaxSustainedTrafficRate; - - /** 32bit Maximum Traffic Burst allowed for the Service Flow*/ - B_UINT32 u32MaxTrafficBurst; - - /** 32bit Minimum Reserved Traffic Rate of the Service Flow*/ - B_UINT32 u32MinReservedTrafficRate; - - /** 32bit Tolerated Jitter of the Service Flow*/ - B_UINT32 u32ToleratedJitter; - - /** 32bit Maximum Latency of the Service Flow*/ - B_UINT32 u32MaximumLatency; - - /** 16bitCID Of The Service Flow*/ - B_UINT16 u16CID; - - /** 16bit SAID on which the service flow being set up shall be mapped*/ - B_UINT16 u16TargetSAID; - - /** 16bit ARQ window size negotiated*/ - B_UINT16 u16ARQWindowSize; - - /** 16bit Total Tx delay incl sending, receiving & processing delays */ - B_UINT16 u16ARQRetryTxTimeOut; - - /** 16bit Total Rx delay incl sending, receiving & processing delays */ - B_UINT16 u16ARQRetryRxTimeOut; - - /** 16bit ARQ block lifetime */ - B_UINT16 u16ARQBlockLifeTime; - - /** 16bit ARQ Sync loss timeout*/ - B_UINT16 u16ARQSyncLossTimeOut; - - /** 16bit ARQ Purge timeout */ - B_UINT16 u16ARQRxPurgeTimeOut; -//TODO::Remove this once we move to a new CORR2 driver - /// \brief Size of an ARQ block - B_UINT16 u16ARQBlockSize; - -//#endif - /** 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP*/ - B_UINT16 u16SDUInterArrivalTime; - - /** 16bit Specifies the time base for rate measurement */ - B_UINT16 u16TimeBase; - - /** 16bit Interval b/w Successive Grant oppurtunities*/ - B_UINT16 u16UnsolicitedGrantInterval; - - /** 16bit Interval b/w Successive Polling grant oppurtunities*/ - B_UINT16 u16UnsolicitedPollingInterval; - - /** internal var to get the overhead */ - B_UINT16 u16MacOverhead; - - /** MBS contents Identifier*/ - B_UINT16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH]; - - /** MBS contents Identifier length*/ - B_UINT8 u8MBSContentsIDLength; - - /** ServiceClassName Length Of The Service Flow*/ - B_UINT8 u8ServiceClassNameLength; - - /** 32bytes ServiceClassName Of The Service Flow*/ - B_UINT8 u8ServiceClassName[32]; - - /** 8bit Indicates whether or not MBS service is requested for this Serivce Flow*/ - B_UINT8 u8MBSService; - - /** 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets*/ - B_UINT8 u8QosParamSet; - - /** 8bit Traffic Priority Of the Service Flow */ - B_UINT8 u8TrafficPriority; - - /** 8bit Uplink Grant Scheduling Type of The Service Flow */ - B_UINT8 u8ServiceFlowSchedulingType; - - /** 8bit Request transmission Policy of the Service Flow*/ - B_UINT8 u8RequesttransmissionPolicy; - - /** 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */ - B_UINT8 u8FixedLengthVSVariableLengthSDUIndicator; - - /** 8bit Length of the SDU for a fixed length SDU service flow*/ - B_UINT8 u8SDUSize; - - /** 8bit Indicates whether or not ARQ is requested for this connection*/ - B_UINT8 u8ARQEnable; - - /**< 8bit Indicates whether or not data has tobe delivered in order to higher layer*/ - B_UINT8 u8ARQDeliverInOrder; - - /** 8bit Receiver ARQ ACK processing time */ - B_UINT8 u8RxARQAckProcessingTime; - - /** 8bit Convergence Sublayer Specification Of The Service Flow*/ - B_UINT8 u8CSSpecification; - - /** 8 bit Type of data delivery service*/ - B_UINT8 u8TypeOfDataDeliveryService; - - /** 8bit Specifies whether a service flow may generate Paging */ - B_UINT8 u8PagingPreference; - - /** 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */ - B_UINT8 u8MBSZoneIdentifierassignment; - - /** 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode*/ - B_UINT8 u8TrafficIndicationPreference; - - /** 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */ - B_UINT8 u8GlobalServicesClassNameLength; - - /** 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */ - B_UINT8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH]; - - /** 8bit Indicates whether or not SN feedback is enabled for the conn */ - B_UINT8 u8SNFeedbackEnabled; - - /** Indicates the size of the Fragment Sequence Number for the connection */ - B_UINT8 u8FSNSize; - - /** 8bit Number of CIDs in active BS list */ - B_UINT8 u8CIDAllocation4activeBSsLength; - - /** CIDs of BS in the active list */ - B_UINT8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS]; - - /** Specifies if PDU extended subheader should be applied on every PDU on this conn*/ - B_UINT8 u8PDUSNExtendedSubheader4HarqReordering; - - /** 8bit Specifies whether the connection uses HARQ or not */ - B_UINT8 u8HARQServiceFlows; - - /** Specifies the length of Authorization token*/ - B_UINT8 u8AuthTokenLength; - - /** Specifies the Authorization token*/ - B_UINT8 u8AuthToken[AUTH_TOKEN_LENGTH]; - - /** specifes Number of HARQ channels used to carry data length*/ - B_UINT8 u8HarqChannelMappingLength; - - /** specifes HARQ channels used to carry data*/ - B_UINT8 u8HARQChannelMapping[NUM_HARQ_CHANNELS]; - - /** 8bit Length of Vendor Specific QoS Params */ - B_UINT8 u8VendorSpecificQoSParamLength; - - /** 1byte Vendor Specific QoS Param Of The Service Flow*/ - B_UINT8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM]; - - // indicates total classifiers in the SF - B_UINT8 u8TotalClassifiers; /**< Total number of valid classifiers*/ - B_UINT8 bValid; /**< Validity flag */ - B_UINT8 u8Padding; /**< Padding byte*/ - -/** -Structure for Convergence SubLayer Types with a maximum of 4 classifiers -*/ - stConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; +typedef struct _stConvergenceSLTypes stConvergenceSLTypes, CConvergenceSLTypes, *pstConvergenceSLTypes; + +/* brief structure CServiceFlowParamSI */ +typedef struct _stServiceFlowParamSI { + /* 32bitSFID Of The Service Flow */ + B_UINT32 u32SFID; + /* 32bit Maximum Sustained Traffic Rate of the Service Flow */ + B_UINT32 u32MaxSustainedTrafficRate; + /* 32bit Maximum Traffic Burst allowed for the Service Flow */ + B_UINT32 u32MaxTrafficBurst; + /* 32bit Minimum Reserved Traffic Rate of the Service Flow */ + B_UINT32 u32MinReservedTrafficRate; + /* 32bit Tolerated Jitter of the Service Flow */ + B_UINT32 u32ToleratedJitter; + /* 32bit Maximum Latency of the Service Flow */ + B_UINT32 u32MaximumLatency; + /* 16bitCID Of The Service Flow */ + B_UINT16 u16CID; + /* 16bit SAID on which the service flow being set up shall be mapped */ + B_UINT16 u16TargetSAID; + /* 16bit ARQ window size negotiated */ + B_UINT16 u16ARQWindowSize; + /* 16bit Total Tx delay incl sending, receiving & processing delays */ + B_UINT16 u16ARQRetryTxTimeOut; + /* 16bit Total Rx delay incl sending, receiving & processing delays */ + B_UINT16 u16ARQRetryRxTimeOut; + /* 16bit ARQ block lifetime */ + B_UINT16 u16ARQBlockLifeTime; + /* 16bit ARQ Sync loss timeout */ + B_UINT16 u16ARQSyncLossTimeOut; + /* 16bit ARQ Purge timeout */ + B_UINT16 u16ARQRxPurgeTimeOut; + /* TODO::Remove this once we move to a new CORR2 driver + * brief Size of an ARQ block + */ + B_UINT16 u16ARQBlockSize; + /* #endif */ + /* 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP */ + B_UINT16 u16SDUInterArrivalTime; + /* 16bit Specifies the time base for rate measurement */ + B_UINT16 u16TimeBase; + /* 16bit Interval b/w Successive Grant oppurtunities */ + B_UINT16 u16UnsolicitedGrantInterval; + /* 16bit Interval b/w Successive Polling grant oppurtunities */ + B_UINT16 u16UnsolicitedPollingInterval; + /* internal var to get the overhead */ + B_UINT16 u16MacOverhead; + /* MBS contents Identifier */ + B_UINT16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH]; + /* MBS contents Identifier length */ + B_UINT8 u8MBSContentsIDLength; + /* ServiceClassName Length Of The Service Flow */ + B_UINT8 u8ServiceClassNameLength; + /* 32bytes ServiceClassName Of The Service Flow */ + B_UINT8 u8ServiceClassName[32]; + /* 8bit Indicates whether or not MBS service is requested for this Serivce Flow */ + B_UINT8 u8MBSService; + /* 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets */ + B_UINT8 u8QosParamSet; + /* 8bit Traffic Priority Of the Service Flow */ + B_UINT8 u8TrafficPriority; + /* 8bit Uplink Grant Scheduling Type of The Service Flow */ + B_UINT8 u8ServiceFlowSchedulingType; + /* 8bit Request transmission Policy of the Service Flow */ + B_UINT8 u8RequesttransmissionPolicy; + /* 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */ + B_UINT8 u8FixedLengthVSVariableLengthSDUIndicator; + /* 8bit Length of the SDU for a fixed length SDU service flow */ + B_UINT8 u8SDUSize; + /* 8bit Indicates whether or not ARQ is requested for this connection */ + B_UINT8 u8ARQEnable; + /* < 8bit Indicates whether or not data has tobe delivered in order to higher layer */ + B_UINT8 u8ARQDeliverInOrder; + /* 8bit Receiver ARQ ACK processing time */ + B_UINT8 u8RxARQAckProcessingTime; + /* 8bit Convergence Sublayer Specification Of The Service Flow */ + B_UINT8 u8CSSpecification; + /* 8 bit Type of data delivery service */ + B_UINT8 u8TypeOfDataDeliveryService; + /* 8bit Specifies whether a service flow may generate Paging */ + B_UINT8 u8PagingPreference; + /* 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */ + B_UINT8 u8MBSZoneIdentifierassignment; + /* 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode */ + B_UINT8 u8TrafficIndicationPreference; + /* 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */ + B_UINT8 u8GlobalServicesClassNameLength; + /* 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */ + B_UINT8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH]; + /* 8bit Indicates whether or not SN feedback is enabled for the conn */ + B_UINT8 u8SNFeedbackEnabled; + /* Indicates the size of the Fragment Sequence Number for the connection */ + B_UINT8 u8FSNSize; + /* 8bit Number of CIDs in active BS list */ + B_UINT8 u8CIDAllocation4activeBSsLength; + /* CIDs of BS in the active list */ + B_UINT8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS]; + /* Specifies if PDU extended subheader should be applied on every PDU on this conn */ + B_UINT8 u8PDUSNExtendedSubheader4HarqReordering; + /* 8bit Specifies whether the connection uses HARQ or not */ + B_UINT8 u8HARQServiceFlows; + /* Specifies the length of Authorization token */ + B_UINT8 u8AuthTokenLength; + /* Specifies the Authorization token */ + B_UINT8 u8AuthToken[AUTH_TOKEN_LENGTH]; + /* specifes Number of HARQ channels used to carry data length */ + B_UINT8 u8HarqChannelMappingLength; + /* specifes HARQ channels used to carry data */ + B_UINT8 u8HARQChannelMapping[NUM_HARQ_CHANNELS]; + /* 8bit Length of Vendor Specific QoS Params */ + B_UINT8 u8VendorSpecificQoSParamLength; + /* 1byte Vendor Specific QoS Param Of The Service Flow */ + B_UINT8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM]; + /* indicates total classifiers in the SF */ + B_UINT8 u8TotalClassifiers; /* < Total number of valid classifiers */ + B_UINT8 bValid; /* < Validity flag */ + B_UINT8 u8Padding; /* < Padding byte */ +/* + * Structure for Convergence SubLayer Types with a maximum of 4 classifiers + */ + stConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; } stServiceFlowParamSI, *pstServiceFlowParamSI; typedef stServiceFlowParamSI CServiceFlowParamSI; -/** -structure stLocalSFAddRequest -*/ -typedef struct _stLocalSFAddRequest{ - - B_UINT8 u8Type; /**< Type*/ - B_UINT8 eConnectionDir; /**< Connection direction*/ - /// \brief 16 bit TID - B_UINT16 u16TID; /**< 16bit TID*/ - /// \brief 16bitCID - B_UINT16 u16CID; /**< 16bit CID*/ - /// \brief 16bitVCID - B_UINT16 u16VCID; /**< 16bit VCID*/ - /// \brief structure ParameterSet - - stServiceFlowParamSI *psfParameterSet; /**< structure ParameterSet*/ - -}stLocalSFAddRequest, *pstLocalSFAddRequest; - - -/** -structure stLocalSFAddIndication -*/ -typedef struct _stLocalSFAddIndication{ - - B_UINT8 u8Type; /**< Type*/ - B_UINT8 eConnectionDir; /**< Connection Direction*/ - /// \brief 16 bit TID - B_UINT16 u16TID; /**< TID*/ - /// \brief 16bitCID - B_UINT16 u16CID; /**< 16bitCID*/ - /// \brief 16bitVCID - B_UINT16 u16VCID; /**< 16bitVCID*/ - - - /// \brief structure AuthorizedSet - /// \brief structure AuthorizedSet - stServiceFlowParamSI *psfAuthorizedSet; /**< AuthorizedSet of type stServiceFlowParamSI*/ - /// \brief structure AdmittedSet - stServiceFlowParamSI *psfAdmittedSet; /**< AdmittedSet of type stServiceFlowParamSI*/ - /// \brief structure ActiveSet - stServiceFlowParamSI *psfActiveSet; /**< sfActiveSet of type stServiceFlowParamSI*/ - B_UINT8 u8CC; /**< Confirmation Code*/ - B_UINT8 u8Padd; /**< 8-bit Padding */ - - B_UINT16 u16Padd; /**< 16 bit Padding */ - -}stLocalSFAddIndication; - +/* + * structure stLocalSFAddRequest + */ +typedef struct _stLocalSFAddRequest { + B_UINT8 u8Type; /* < Type */ + B_UINT8 eConnectionDir; /* < Connection direction */ + /* brief 16 bit TID */ + B_UINT16 u16TID; /* < 16bit TID */ + /* brief 16bitCID */ + B_UINT16 u16CID; /* < 16bit CID */ + /* brief 16bitVCID */ + B_UINT16 u16VCID; /* < 16bit VCID */ + /* brief structure ParameterSet */ + stServiceFlowParamSI *psfParameterSet; /* < structure ParameterSet */ + +} stLocalSFAddRequest, *pstLocalSFAddRequest; + +/* + * structure stLocalSFAddIndication + */ +typedef struct _stLocalSFAddIndication { + B_UINT8 u8Type; /* < Type */ + B_UINT8 eConnectionDir; /* < Connection Direction */ + /* brief 16 bit TID */ + B_UINT16 u16TID; /* < TID */ + /* brief 16bitCID */ + B_UINT16 u16CID; /* < 16bitCID */ + /* brief 16bitVCID */ + B_UINT16 u16VCID; /* < 16bitVCID */ + /* brief structure AuthorizedSet */ + /* brief structure AuthorizedSet */ + stServiceFlowParamSI *psfAuthorizedSet; /* < AuthorizedSet of type stServiceFlowParamSI */ + /* brief structure AdmittedSet */ + stServiceFlowParamSI *psfAdmittedSet; /* < AdmittedSet of type stServiceFlowParamSI */ + /* brief structure ActiveSet */ + stServiceFlowParamSI *psfActiveSet; /* < sfActiveSet of type stServiceFlowParamSI */ + B_UINT8 u8CC; /* <Confirmation Code */ + B_UINT8 u8Padd; /* < 8-bit Padding */ + B_UINT16 u16Padd; /* < 16 bit Padding */ + +} stLocalSFAddIndication; typedef struct _stLocalSFAddIndication *pstLocalSFAddIndication; -/** -structure stLocalSFChangeRequest is same as structure stLocalSFAddIndication -*/ +/* + * structure stLocalSFChangeRequest is same as structure stLocalSFAddIndication + */ typedef struct _stLocalSFAddIndication stLocalSFChangeRequest, *pstLocalSFChangeRequest; -/** -structure stLocalSFChangeIndication is same as structure stLocalSFAddIndication -*/ +/* + * structure stLocalSFChangeIndication is same as structure stLocalSFAddIndication + */ typedef struct _stLocalSFAddIndication stLocalSFChangeIndication, *pstLocalSFChangeIndication; -/** -structure stLocalSFDeleteRequest -*/ -typedef struct _stLocalSFDeleteRequest{ - B_UINT8 u8Type; /**< Type*/ - B_UINT8 u8Padding; /**< Padding byte*/ - B_UINT16 u16TID; /**< TID*/ - /// \brief 32bitSFID - B_UINT32 u32SFID; /**< SFID*/ -}stLocalSFDeleteRequest, *pstLocalSFDeleteRequest; - -/** -structure stLocalSFDeleteIndication -*/ -typedef struct stLocalSFDeleteIndication{ - B_UINT8 u8Type; /**< Type */ - B_UINT8 u8Padding; /**< Padding */ - B_UINT16 u16TID; /**< TID */ - /// \brief 16bitCID - B_UINT16 u16CID; /**< CID */ - /// \brief 16bitVCID - B_UINT16 u16VCID; /**< VCID */ - /// \brief 32bitSFID - B_UINT32 u32SFID; /**< SFID */ - /// \brief 8bit Confirmation code - B_UINT8 u8ConfirmationCode; /**< Confirmation code */ - B_UINT8 u8Padding1[3]; /**< 3 byte Padding */ -}stLocalSFDeleteIndication; - -typedef struct _stIM_SFHostNotify -{ - B_UINT32 SFID; //SFID of the service flow - B_UINT16 newCID; //the new/changed CID - B_UINT16 VCID; //Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid - B_UINT8 RetainSF; //Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete - B_UINT8 QoSParamSet; //QoS paramset of the retained SF - B_UINT16 u16reserved; //For byte alignment - -} stIM_SFHostNotify; +/* + * structure stLocalSFDeleteRequest + */ +typedef struct _stLocalSFDeleteRequest { + B_UINT8 u8Type; /* < Type */ + B_UINT8 u8Padding; /* < Padding byte */ + B_UINT16 u16TID; /* < TID */ + /* brief 32bitSFID */ + B_UINT32 u32SFID; /* < SFID */ +} stLocalSFDeleteRequest, *pstLocalSFDeleteRequest; + +/* + * structure stLocalSFDeleteIndication + */ +typedef struct stLocalSFDeleteIndication { + B_UINT8 u8Type; /* < Type */ + B_UINT8 u8Padding; /* < Padding */ + B_UINT16 u16TID; /* < TID */ + /* brief 16bitCID */ + B_UINT16 u16CID; /* < CID */ + /* brief 16bitVCID */ + B_UINT16 u16VCID; /* < VCID */ + /* brief 32bitSFID */ + B_UINT32 u32SFID; /* < SFID */ + /* brief 8bit Confirmation code */ + B_UINT8 u8ConfirmationCode; /* < Confirmation code */ + B_UINT8 u8Padding1[3]; /* < 3 byte Padding */ +} stLocalSFDeleteIndication; + +struct bcm_stim_sfhostnotify { + B_UINT32 SFID; /* SFID of the service flow */ + B_UINT16 newCID; /* the new/changed CID */ + B_UINT16 VCID; /* Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid */ + B_UINT8 RetainSF; /* Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete */ + B_UINT8 QoSParamSet; /* QoS paramset of the retained SF */ + B_UINT16 u16reserved; /* For byte alignment */ +}; #endif diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c index 693c4544c29d..c9492edaaddb 100644 --- a/drivers/staging/ced1401/ced_ioc.c +++ b/drivers/staging/ced1401/ced_ioc.c @@ -837,7 +837,7 @@ int SetEvent(DEVICE_EXTENSION * pdx, TRANSFEREVENT __user * pTE) int WaitEvent(DEVICE_EXTENSION * pdx, int nArea, int msTimeOut) { int iReturn; - if ((unsigned)nArea > MAX_TRANSAREAS) + if ((unsigned)nArea >= MAX_TRANSAREAS) return U14ERR_BADAREA; else { int iWait; @@ -884,7 +884,7 @@ int WaitEvent(DEVICE_EXTENSION * pdx, int nArea, int msTimeOut) int TestEvent(DEVICE_EXTENSION * pdx, int nArea) { int iReturn; - if ((unsigned)nArea > MAX_TRANSAREAS) + if ((unsigned)nArea >= MAX_TRANSAREAS) iReturn = U14ERR_BADAREA; else { TRANSAREA *pTA = &pdx->rTransDef[nArea]; diff --git a/drivers/staging/ced1401/usb1401.c b/drivers/staging/ced1401/usb1401.c index 69b7f20c9d51..6ba0ef652561 100644 --- a/drivers/staging/ced1401/usb1401.c +++ b/drivers/staging/ced1401/usb1401.c @@ -261,24 +261,6 @@ static int ced_flush(struct file *file, fl_owner_t id) return res; } -static ssize_t ced_read(struct file *file, char *buffer, size_t count, - loff_t * ppos) -{ - DEVICE_EXTENSION *pdx = file->private_data; - dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb", - __func__); - return 0; // as we do not do reads this way -} - -static ssize_t ced_write(struct file *file, const char *user_buffer, - size_t count, loff_t * ppos) -{ - DEVICE_EXTENSION *pdx = file->private_data; - dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb", - __func__); - return 0; -} - /*************************************************************************** ** CanAcceptIoRequests ** If the device is removed, interface is set NULL. We also clear our pointer @@ -1402,8 +1384,6 @@ static int ced_ioctl(struct inode *node, struct file *file, unsigned int cmd, static const struct file_operations ced_fops = { .owner = THIS_MODULE, - .read = ced_read, - .write = ced_write, .open = ced_open, .release = ced_release, .flush = ced_flush, @@ -1653,19 +1633,5 @@ static struct usb_driver ced_driver = { .supports_autosuspend = 1, }; -static int __init usb_skel_init(void) -{ - /* register this driver with the USB subsystem */ - return usb_register(&ced_driver); -} - -static void __exit usb_skel_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&ced_driver); -} - -module_init(usb_skel_init); -module_exit(usb_skel_exit); - +module_usb_driver(ced_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 8ea55aef10a7..133f013e0f6d 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -208,92 +208,92 @@ /* subdevice types */ - enum comedi_subdevice_type { - COMEDI_SUBD_UNUSED, /* unused by driver */ - COMEDI_SUBD_AI, /* analog input */ - COMEDI_SUBD_AO, /* analog output */ - COMEDI_SUBD_DI, /* digital input */ - COMEDI_SUBD_DO, /* digital output */ - COMEDI_SUBD_DIO, /* digital input/output */ - COMEDI_SUBD_COUNTER, /* counter */ - COMEDI_SUBD_TIMER, /* timer */ - COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ - COMEDI_SUBD_CALIB, /* calibration DACs */ - COMEDI_SUBD_PROC, /* processor, DSP */ - COMEDI_SUBD_SERIAL, /* serial IO */ - COMEDI_SUBD_PWM /* PWM */ - }; +enum comedi_subdevice_type { + COMEDI_SUBD_UNUSED, /* unused by driver */ + COMEDI_SUBD_AI, /* analog input */ + COMEDI_SUBD_AO, /* analog output */ + COMEDI_SUBD_DI, /* digital input */ + COMEDI_SUBD_DO, /* digital output */ + COMEDI_SUBD_DIO, /* digital input/output */ + COMEDI_SUBD_COUNTER, /* counter */ + COMEDI_SUBD_TIMER, /* timer */ + COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ + COMEDI_SUBD_CALIB, /* calibration DACs */ + COMEDI_SUBD_PROC, /* processor, DSP */ + COMEDI_SUBD_SERIAL, /* serial IO */ + COMEDI_SUBD_PWM /* PWM */ +}; /* configuration instructions */ - enum configuration_ids { - INSN_CONFIG_DIO_INPUT = 0, - INSN_CONFIG_DIO_OUTPUT = 1, - INSN_CONFIG_DIO_OPENDRAIN = 2, - INSN_CONFIG_ANALOG_TRIG = 16, +enum configuration_ids { + INSN_CONFIG_DIO_INPUT = 0, + INSN_CONFIG_DIO_OUTPUT = 1, + INSN_CONFIG_DIO_OPENDRAIN = 2, + INSN_CONFIG_ANALOG_TRIG = 16, /* INSN_CONFIG_WAVEFORM = 17, */ /* INSN_CONFIG_TRIG = 18, */ /* INSN_CONFIG_COUNTER = 19, */ - INSN_CONFIG_ALT_SOURCE = 20, - INSN_CONFIG_DIGITAL_TRIG = 21, - INSN_CONFIG_BLOCK_SIZE = 22, - INSN_CONFIG_TIMER_1 = 23, - INSN_CONFIG_FILTER = 24, - INSN_CONFIG_CHANGE_NOTIFY = 25, - - /*ALPHA*/ INSN_CONFIG_SERIAL_CLOCK = 26, - INSN_CONFIG_BIDIRECTIONAL_DATA = 27, - INSN_CONFIG_DIO_QUERY = 28, - INSN_CONFIG_PWM_OUTPUT = 29, - INSN_CONFIG_GET_PWM_OUTPUT = 30, - INSN_CONFIG_ARM = 31, - INSN_CONFIG_DISARM = 32, - INSN_CONFIG_GET_COUNTER_STATUS = 33, - INSN_CONFIG_RESET = 34, - /* Use CTR as single pulsegenerator */ - INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, - /* Use CTR as pulsetraingenerator */ - INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, - /* Use the counter as encoder */ - INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, - INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ - INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ - /* Set master clock source */ - INSN_CONFIG_SET_CLOCK_SRC = 2003, - INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ - INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ - /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ - /* Get size in bytes of subdevice's on-board fifos used during - * streaming input/output */ - INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, - INSN_CONFIG_SET_COUNTER_MODE = 4097, - /* INSN_CONFIG_8254_SET_MODE is deprecated */ - INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, - INSN_CONFIG_8254_READ_STATUS = 4098, - INSN_CONFIG_SET_ROUTING = 4099, - INSN_CONFIG_GET_ROUTING = 4109, -/* PWM */ - INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ - INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ - INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ - /* sets H bridge: duty cycle and sign bit for a relay at the - * same time */ - INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, - /* gets H bridge data: duty cycle and the sign bit */ - INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 - }; - - enum comedi_io_direction { - COMEDI_INPUT = 0, - COMEDI_OUTPUT = 1, - COMEDI_OPENDRAIN = 2 - }; - - enum comedi_support_level { - COMEDI_UNKNOWN_SUPPORT = 0, - COMEDI_SUPPORTED, - COMEDI_UNSUPPORTED - }; + INSN_CONFIG_ALT_SOURCE = 20, + INSN_CONFIG_DIGITAL_TRIG = 21, + INSN_CONFIG_BLOCK_SIZE = 22, + INSN_CONFIG_TIMER_1 = 23, + INSN_CONFIG_FILTER = 24, + INSN_CONFIG_CHANGE_NOTIFY = 25, + + INSN_CONFIG_SERIAL_CLOCK = 26, /*ALPHA*/ + INSN_CONFIG_BIDIRECTIONAL_DATA = 27, + INSN_CONFIG_DIO_QUERY = 28, + INSN_CONFIG_PWM_OUTPUT = 29, + INSN_CONFIG_GET_PWM_OUTPUT = 30, + INSN_CONFIG_ARM = 31, + INSN_CONFIG_DISARM = 32, + INSN_CONFIG_GET_COUNTER_STATUS = 33, + INSN_CONFIG_RESET = 34, + /* Use CTR as single pulsegenerator */ + INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, + /* Use CTR as pulsetraingenerator */ + INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, + /* Use the counter as encoder */ + INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, + INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ + INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ + /* Set master clock source */ + INSN_CONFIG_SET_CLOCK_SRC = 2003, + INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ + INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ + /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ + /* Get size in bytes of subdevice's on-board fifos used during + * streaming input/output */ + INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, + INSN_CONFIG_SET_COUNTER_MODE = 4097, + /* INSN_CONFIG_8254_SET_MODE is deprecated */ + INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, + INSN_CONFIG_8254_READ_STATUS = 4098, + INSN_CONFIG_SET_ROUTING = 4099, + INSN_CONFIG_GET_ROUTING = 4109, + /* PWM */ + INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ + INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ + INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ + /* sets H bridge: duty cycle and sign bit for a relay at the + * same time */ + INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, + /* gets H bridge data: duty cycle and the sign bit */ + INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 +}; + +enum comedi_io_direction { + COMEDI_INPUT = 0, + COMEDI_OUTPUT = 1, + COMEDI_OPENDRAIN = 2 +}; + +enum comedi_support_level { + COMEDI_UNKNOWN_SUPPORT = 0, + COMEDI_SUPPORTED, + COMEDI_UNSUPPORTED +}; /* ioctls */ @@ -317,133 +317,133 @@ /* structures */ - struct comedi_trig { - unsigned int subdev; /* subdevice */ - unsigned int mode; /* mode */ - unsigned int flags; - unsigned int n_chan; /* number of channels */ - unsigned int *chanlist; /* channel/range list */ - short *data; /* data list, size depends on subd flags */ - unsigned int n; /* number of scans */ - unsigned int trigsrc; - unsigned int trigvar; - unsigned int trigvar1; - unsigned int data_len; - unsigned int unused[3]; - }; - - struct comedi_insn { - unsigned int insn; - unsigned int n; - unsigned int __user *data; - unsigned int subdev; - unsigned int chanspec; - unsigned int unused[3]; - }; - - struct comedi_insnlist { - unsigned int n_insns; - struct comedi_insn __user *insns; - }; - - struct comedi_cmd { - unsigned int subdev; - unsigned int flags; - - unsigned int start_src; - unsigned int start_arg; - - unsigned int scan_begin_src; - unsigned int scan_begin_arg; - - unsigned int convert_src; - unsigned int convert_arg; - - unsigned int scan_end_src; - unsigned int scan_end_arg; - - unsigned int stop_src; - unsigned int stop_arg; - - unsigned int __user *chanlist; /* channel/range list */ - unsigned int chanlist_len; - - short __user *data; /* data list, size depends on subd flags */ - unsigned int data_len; - }; - - struct comedi_chaninfo { - unsigned int subdev; - unsigned int __user *maxdata_list; - unsigned int __user *flaglist; - unsigned int __user *rangelist; - unsigned int unused[4]; - }; - - struct comedi_rangeinfo { - unsigned int range_type; - void __user *range_ptr; - }; - - struct comedi_krange { - int min; /* fixed point, multiply by 1e-6 */ - int max; /* fixed point, multiply by 1e-6 */ - unsigned int flags; - }; - - struct comedi_subdinfo { - unsigned int type; - unsigned int n_chan; - unsigned int subd_flags; - unsigned int timer_type; - unsigned int len_chanlist; - unsigned int maxdata; - unsigned int flags; /* channel flags */ - unsigned int range_type; /* lookup in kernel */ - unsigned int settling_time_0; - /* see support_level enum for values */ - unsigned insn_bits_support; - unsigned int unused[8]; - }; - - struct comedi_devinfo { - unsigned int version_code; - unsigned int n_subdevs; - char driver_name[COMEDI_NAMELEN]; - char board_name[COMEDI_NAMELEN]; - int read_subdevice; - int write_subdevice; - int unused[30]; - }; - - struct comedi_devconfig { - char board_name[COMEDI_NAMELEN]; - int options[COMEDI_NDEVCONFOPTS]; - }; - - struct comedi_bufconfig { - unsigned int subdevice; - unsigned int flags; - - unsigned int maximum_size; - unsigned int size; - - unsigned int unused[4]; - }; - - struct comedi_bufinfo { - unsigned int subdevice; - unsigned int bytes_read; - - unsigned int buf_write_ptr; - unsigned int buf_read_ptr; - unsigned int buf_write_count; - unsigned int buf_read_count; - - unsigned int bytes_written; - - unsigned int unused[4]; - }; +struct comedi_trig { + unsigned int subdev; /* subdevice */ + unsigned int mode; /* mode */ + unsigned int flags; + unsigned int n_chan; /* number of channels */ + unsigned int *chanlist; /* channel/range list */ + short *data; /* data list, size depends on subd flags */ + unsigned int n; /* number of scans */ + unsigned int trigsrc; + unsigned int trigvar; + unsigned int trigvar1; + unsigned int data_len; + unsigned int unused[3]; +}; + +struct comedi_insn { + unsigned int insn; + unsigned int n; + unsigned int __user *data; + unsigned int subdev; + unsigned int chanspec; + unsigned int unused[3]; +}; + +struct comedi_insnlist { + unsigned int n_insns; + struct comedi_insn __user *insns; +}; + +struct comedi_cmd { + unsigned int subdev; + unsigned int flags; + + unsigned int start_src; + unsigned int start_arg; + + unsigned int scan_begin_src; + unsigned int scan_begin_arg; + + unsigned int convert_src; + unsigned int convert_arg; + + unsigned int scan_end_src; + unsigned int scan_end_arg; + + unsigned int stop_src; + unsigned int stop_arg; + + unsigned int *chanlist; /* channel/range list */ + unsigned int chanlist_len; + + short __user *data; /* data list, size depends on subd flags */ + unsigned int data_len; +}; + +struct comedi_chaninfo { + unsigned int subdev; + unsigned int __user *maxdata_list; + unsigned int __user *flaglist; + unsigned int __user *rangelist; + unsigned int unused[4]; +}; + +struct comedi_rangeinfo { + unsigned int range_type; + void __user *range_ptr; +}; + +struct comedi_krange { + int min; /* fixed point, multiply by 1e-6 */ + int max; /* fixed point, multiply by 1e-6 */ + unsigned int flags; +}; + +struct comedi_subdinfo { + unsigned int type; + unsigned int n_chan; + unsigned int subd_flags; + unsigned int timer_type; + unsigned int len_chanlist; + unsigned int maxdata; + unsigned int flags; /* channel flags */ + unsigned int range_type; /* lookup in kernel */ + unsigned int settling_time_0; + /* see support_level enum for values */ + unsigned insn_bits_support; + unsigned int unused[8]; +}; + +struct comedi_devinfo { + unsigned int version_code; + unsigned int n_subdevs; + char driver_name[COMEDI_NAMELEN]; + char board_name[COMEDI_NAMELEN]; + int read_subdevice; + int write_subdevice; + int unused[30]; +}; + +struct comedi_devconfig { + char board_name[COMEDI_NAMELEN]; + int options[COMEDI_NDEVCONFOPTS]; +}; + +struct comedi_bufconfig { + unsigned int subdevice; + unsigned int flags; + + unsigned int maximum_size; + unsigned int size; + + unsigned int unused[4]; +}; + +struct comedi_bufinfo { + unsigned int subdevice; + unsigned int bytes_read; + + unsigned int buf_write_ptr; + unsigned int buf_read_ptr; + unsigned int buf_write_count; + unsigned int buf_read_count; + + unsigned int bytes_written; + + unsigned int unused[4]; +}; /* range stuff */ @@ -495,306 +495,306 @@ */ - enum i8254_mode { - I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ - I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ - I8254_MODE2 = (2 << 1), /* Rate generator */ - I8254_MODE3 = (3 << 1), /* Square wave mode */ - I8254_MODE4 = (4 << 1), /* Software triggered strobe */ - I8254_MODE5 = (5 << 1), /* Hardware triggered strobe - * (retriggerable) */ - I8254_BCD = 1, /* use binary-coded decimal instead of binary +enum i8254_mode { + I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ + I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ + I8254_MODE2 = (2 << 1), /* Rate generator */ + I8254_MODE3 = (3 << 1), /* Square wave mode */ + I8254_MODE4 = (4 << 1), /* Software triggered strobe */ + I8254_MODE5 = (5 << 1), /* Hardware triggered strobe + * (retriggerable) */ + I8254_BCD = 1, /* use binary-coded decimal instead of binary * (pretty useless) */ - I8254_BINARY = 0 - }; - - static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) - { - if (pfi_channel < 10) - return 0x1 + pfi_channel; - else - return 0xb + pfi_channel; - } - - static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) - { - if (rtsi_channel < 7) - return 0xb + rtsi_channel; - else - return 0x1b; - } + I8254_BINARY = 0 +}; + +static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) +{ + if (pfi_channel < 10) + return 0x1 + pfi_channel; + else + return 0xb + pfi_channel; +} + +static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) +{ + if (rtsi_channel < 7) + return 0xb + rtsi_channel; + else + return 0x1b; +} /* mode bits for NI general-purpose counters, set with * INSN_CONFIG_SET_COUNTER_MODE */ #define NI_GPCT_COUNTING_MODE_SHIFT 16 #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 - enum ni_gpct_mode_bits { - NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, - NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, - NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, - NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, - NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, - NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, - NI_GPCT_STOP_MODE_MASK = 0x60, - NI_GPCT_STOP_ON_GATE_BITS = 0x00, - NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, - NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, - NI_GPCT_LOAD_B_SELECT_BIT = 0x80, - NI_GPCT_OUTPUT_MODE_MASK = 0x300, - NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, - NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, - NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, - NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, - NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, - NI_GPCT_DISARM_AT_TC_BITS = 0x400, - NI_GPCT_DISARM_AT_GATE_BITS = 0x800, - NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, - NI_GPCT_LOADING_ON_TC_BIT = 0x1000, - NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, - NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_NORMAL_BITS = - 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = - 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = - 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = - 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = - 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = - 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, - NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = - 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = - 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = - 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = - 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, - NI_GPCT_INDEX_ENABLE_BIT = 0x400000, - NI_GPCT_COUNTING_DIRECTION_MASK = - 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = - 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_UP_BITS = - 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = - 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = - 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, - NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, - NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, - NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, - NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, - NI_GPCT_OR_GATE_BIT = 0x10000000, - NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 - }; +enum ni_gpct_mode_bits { + NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, + NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, + NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, + NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, + NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, + NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, + NI_GPCT_STOP_MODE_MASK = 0x60, + NI_GPCT_STOP_ON_GATE_BITS = 0x00, + NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, + NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, + NI_GPCT_LOAD_B_SELECT_BIT = 0x80, + NI_GPCT_OUTPUT_MODE_MASK = 0x300, + NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, + NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, + NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, + NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, + NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, + NI_GPCT_DISARM_AT_TC_BITS = 0x400, + NI_GPCT_DISARM_AT_GATE_BITS = 0x800, + NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, + NI_GPCT_LOADING_ON_TC_BIT = 0x1000, + NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, + NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_NORMAL_BITS = + 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = + 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = + 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = + 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = + 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = + 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, + NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = + 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = + 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = + 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = + 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, + NI_GPCT_INDEX_ENABLE_BIT = 0x400000, + NI_GPCT_COUNTING_DIRECTION_MASK = + 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = + 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_UP_BITS = + 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = + 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = + 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, + NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, + NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, + NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, + NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, + NI_GPCT_OR_GATE_BIT = 0x10000000, + NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 +}; /* Bits for setting a clock source with * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ - enum ni_gpct_clock_source_bits { - NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, - NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, - NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, - NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, - NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, - NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, - NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, - /* NI 660x-specific */ - NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, - NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, - NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, - NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, - NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, - NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, - /* divide source by 2 */ - NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, - /* divide source by 8 */ - NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, - NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 - }; - static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) - { - /* NI 660x-specific */ - return 0x10 + n; - } - static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) - { - return 0x18 + n; - } - static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) - { - /* no pfi on NI 660x */ - return 0x20 + n; - } +enum ni_gpct_clock_source_bits { + NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, + NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, + NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, + NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, + NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, + NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, + NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, + /* NI 660x-specific */ + NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, + NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, + NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, + NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, + NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, + NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, + /* divide source by 2 */ + NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, + /* divide source by 8 */ + NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, + NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 +}; +static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) +{ + /* NI 660x-specific */ + return 0x10 + n; +} +static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) +{ + return 0x18 + n; +} +static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) +{ + /* no pfi on NI 660x */ + return 0x20 + n; +} /* Possibilities for setting a gate source with INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. May be bitwise-or'd with CR_EDGE or CR_INVERT. */ - enum ni_gpct_gate_select { - /* m-series gates */ - NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, - NI_GPCT_AI_START2_GATE_SELECT = 0x12, - NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, - NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, - NI_GPCT_AI_START1_GATE_SELECT = 0x1c, - NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, - NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, - NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, - /* more gates for 660x */ - NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, - NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, - /* more gates for 660x "second gate" */ - NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, - NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, - /* m-series "second gate" sources are unknown, - * we should add them here with an offset of 0x300 when - * known. */ - NI_GPCT_DISABLED_GATE_SELECT = 0x8000, - }; - static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) - { - return 0x102 + n; - } - static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) - { - return NI_USUAL_RTSI_SELECT(n); - } - static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) - { - return NI_USUAL_PFI_SELECT(n); - } - static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) - { - return 0x202 + n; - } +enum ni_gpct_gate_select { + /* m-series gates */ + NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, + NI_GPCT_AI_START2_GATE_SELECT = 0x12, + NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, + NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, + NI_GPCT_AI_START1_GATE_SELECT = 0x1c, + NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, + NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, + NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, + /* more gates for 660x */ + NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, + NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, + /* more gates for 660x "second gate" */ + NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, + NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, + /* m-series "second gate" sources are unknown, + * we should add them here with an offset of 0x300 when + * known. */ + NI_GPCT_DISABLED_GATE_SELECT = 0x8000, +}; +static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) +{ + return 0x102 + n; +} +static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) +{ + return NI_USUAL_RTSI_SELECT(n); +} +static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) +{ + return NI_USUAL_PFI_SELECT(n); +} +static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) +{ + return 0x202 + n; +} /* Possibilities for setting a source with INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ - enum ni_gpct_other_index { - NI_GPCT_SOURCE_ENCODER_A, - NI_GPCT_SOURCE_ENCODER_B, - NI_GPCT_SOURCE_ENCODER_Z - }; - enum ni_gpct_other_select { - /* m-series gates */ - /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ - NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, - }; - static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) - { - return NI_USUAL_PFI_SELECT(n); - } +enum ni_gpct_other_index { + NI_GPCT_SOURCE_ENCODER_A, + NI_GPCT_SOURCE_ENCODER_B, + NI_GPCT_SOURCE_ENCODER_Z +}; +enum ni_gpct_other_select { + /* m-series gates */ + /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ + NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, +}; +static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) +{ + return NI_USUAL_PFI_SELECT(n); +} /* start sources for ni general-purpose counters for use with INSN_CONFIG_ARM */ - enum ni_gpct_arm_source { - NI_GPCT_ARM_IMMEDIATE = 0x0, - NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter - * and the adjacent paired - * counter simultaneously */ - /* NI doesn't document bits for selecting hardware arm triggers. - * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least - * significant bits (3 bits for 660x or 5 bits for m-series) - * through to the hardware. This will at least allow someone to - * figure out what the bits do later. */ - NI_GPCT_ARM_UNKNOWN = 0x1000, - }; +enum ni_gpct_arm_source { + NI_GPCT_ARM_IMMEDIATE = 0x0, + NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter + * and the adjacent paired + * counter simultaneously */ + /* NI doesn't document bits for selecting hardware arm triggers. + * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least + * significant bits (3 bits for 660x or 5 bits for m-series) + * through to the hardware. This will at least allow someone to + * figure out what the bits do later. */ + NI_GPCT_ARM_UNKNOWN = 0x1000, +}; /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */ - enum ni_gpct_filter_select { - NI_GPCT_FILTER_OFF = 0x0, - NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, - NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, - NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, - NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, - NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, - NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 - }; +enum ni_gpct_filter_select { + NI_GPCT_FILTER_OFF = 0x0, + NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, + NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, + NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, + NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, + NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, + NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 +}; /* PFI digital filtering options for ni m-series for use with * INSN_CONFIG_FILTER. */ - enum ni_pfi_filter_select { - NI_PFI_FILTER_OFF = 0x0, - NI_PFI_FILTER_125ns = 0x1, - NI_PFI_FILTER_6425ns = 0x2, - NI_PFI_FILTER_2550us = 0x3 - }; +enum ni_pfi_filter_select { + NI_PFI_FILTER_OFF = 0x0, + NI_PFI_FILTER_125ns = 0x1, + NI_PFI_FILTER_6425ns = 0x2, + NI_PFI_FILTER_2550us = 0x3 +}; /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ - enum ni_mio_clock_source { - NI_MIO_INTERNAL_CLOCK = 0, - NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use - NI_MIO_PLL_RTSI_CLOCK() */ - /* the NI_MIO_PLL_* sources are m-series only */ - NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, - NI_MIO_PLL_PXI10_CLOCK = 3, - NI_MIO_PLL_RTSI0_CLOCK = 4 - }; - static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) - { - return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; - } +enum ni_mio_clock_source { + NI_MIO_INTERNAL_CLOCK = 0, + NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use + NI_MIO_PLL_RTSI_CLOCK() */ + /* the NI_MIO_PLL_* sources are m-series only */ + NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, + NI_MIO_PLL_PXI10_CLOCK = 3, + NI_MIO_PLL_RTSI0_CLOCK = 4 +}; +static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) +{ + return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; +} /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. The numbers assigned are not arbitrary, they correspond to the bits required to program the board. */ - enum ni_rtsi_routing { - NI_RTSI_OUTPUT_ADR_START1 = 0, - NI_RTSI_OUTPUT_ADR_START2 = 1, - NI_RTSI_OUTPUT_SCLKG = 2, - NI_RTSI_OUTPUT_DACUPDN = 3, - NI_RTSI_OUTPUT_DA_START1 = 4, - NI_RTSI_OUTPUT_G_SRC0 = 5, - NI_RTSI_OUTPUT_G_GATE0 = 6, - NI_RTSI_OUTPUT_RGOUT0 = 7, - NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, - NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI - * clock on line 7 */ - }; - static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) - { - return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; - } +enum ni_rtsi_routing { + NI_RTSI_OUTPUT_ADR_START1 = 0, + NI_RTSI_OUTPUT_ADR_START2 = 1, + NI_RTSI_OUTPUT_SCLKG = 2, + NI_RTSI_OUTPUT_DACUPDN = 3, + NI_RTSI_OUTPUT_DA_START1 = 4, + NI_RTSI_OUTPUT_G_SRC0 = 5, + NI_RTSI_OUTPUT_G_GATE0 = 6, + NI_RTSI_OUTPUT_RGOUT0 = 7, + NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, + NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI + * clock on line 7 */ +}; +static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) +{ + return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; +} /* Signals which can be routed to an NI PFI pin on an m-series board with * INSN_CONFIG_SET_ROUTING. These numbers are also returned by * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing * cannot be changed. The numbers assigned are not arbitrary, they correspond * to the bits required to program the board. */ - enum ni_pfi_routing { - NI_PFI_OUTPUT_PFI_DEFAULT = 0, - NI_PFI_OUTPUT_AI_START1 = 1, - NI_PFI_OUTPUT_AI_START2 = 2, - NI_PFI_OUTPUT_AI_CONVERT = 3, - NI_PFI_OUTPUT_G_SRC1 = 4, - NI_PFI_OUTPUT_G_GATE1 = 5, - NI_PFI_OUTPUT_AO_UPDATE_N = 6, - NI_PFI_OUTPUT_AO_START1 = 7, - NI_PFI_OUTPUT_AI_START_PULSE = 8, - NI_PFI_OUTPUT_G_SRC0 = 9, - NI_PFI_OUTPUT_G_GATE0 = 10, - NI_PFI_OUTPUT_EXT_STROBE = 11, - NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, - NI_PFI_OUTPUT_GOUT0 = 13, - NI_PFI_OUTPUT_GOUT1 = 14, - NI_PFI_OUTPUT_FREQ_OUT = 15, - NI_PFI_OUTPUT_PFI_DO = 16, - NI_PFI_OUTPUT_I_ATRIG = 17, - NI_PFI_OUTPUT_RTSI0 = 18, - NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, - NI_PFI_OUTPUT_SCXI_TRIG1 = 27, - NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, - NI_PFI_OUTPUT_CDI_SAMPLE = 29, - NI_PFI_OUTPUT_CDO_UPDATE = 30 - }; - static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) - { - return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; - } +enum ni_pfi_routing { + NI_PFI_OUTPUT_PFI_DEFAULT = 0, + NI_PFI_OUTPUT_AI_START1 = 1, + NI_PFI_OUTPUT_AI_START2 = 2, + NI_PFI_OUTPUT_AI_CONVERT = 3, + NI_PFI_OUTPUT_G_SRC1 = 4, + NI_PFI_OUTPUT_G_GATE1 = 5, + NI_PFI_OUTPUT_AO_UPDATE_N = 6, + NI_PFI_OUTPUT_AO_START1 = 7, + NI_PFI_OUTPUT_AI_START_PULSE = 8, + NI_PFI_OUTPUT_G_SRC0 = 9, + NI_PFI_OUTPUT_G_GATE0 = 10, + NI_PFI_OUTPUT_EXT_STROBE = 11, + NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, + NI_PFI_OUTPUT_GOUT0 = 13, + NI_PFI_OUTPUT_GOUT1 = 14, + NI_PFI_OUTPUT_FREQ_OUT = 15, + NI_PFI_OUTPUT_PFI_DO = 16, + NI_PFI_OUTPUT_I_ATRIG = 17, + NI_PFI_OUTPUT_RTSI0 = 18, + NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, + NI_PFI_OUTPUT_SCXI_TRIG1 = 27, + NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, + NI_PFI_OUTPUT_CDI_SAMPLE = 29, + NI_PFI_OUTPUT_CDO_UPDATE = 30 +}; +static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) +{ + return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; +} /* Signals which can be routed to output on a NI PFI pin on a 660x board with INSN_CONFIG_SET_ROUTING. The numbers assigned are @@ -802,113 +802,112 @@ INSN_CONFIG_ARM */ to program the board. Lines 0 to 7 can only be set to NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to NI_660X_PFI_OUTPUT_COUNTER. */ - enum ni_660x_pfi_routing { - NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ - NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ - }; +enum ni_660x_pfi_routing { + NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ + NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ +}; /* NI External Trigger lines. These values are not arbitrary, but are related * to the bits required to program the board (offset by 1 for historical * reasons). */ - static inline unsigned NI_EXT_PFI(unsigned pfi_channel) - { - return NI_USUAL_PFI_SELECT(pfi_channel) - 1; - } - static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) - { - return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; - } +static inline unsigned NI_EXT_PFI(unsigned pfi_channel) +{ + return NI_USUAL_PFI_SELECT(pfi_channel) - 1; +} +static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) +{ + return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; +} /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ - enum comedi_counter_status_flags { - COMEDI_COUNTER_ARMED = 0x1, - COMEDI_COUNTER_COUNTING = 0x2, - COMEDI_COUNTER_TERMINAL_COUNT = 0x4, - }; +enum comedi_counter_status_flags { + COMEDI_COUNTER_ARMED = 0x1, + COMEDI_COUNTER_COUNTING = 0x2, + COMEDI_COUNTER_TERMINAL_COUNT = 0x4, +}; /* Clock sources for CDIO subdevice on NI m-series boards. Used as the * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd * with CR_INVERT to change polarity. */ - enum ni_m_series_cdio_scan_begin_src { - NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, - NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, - NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, - NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, - NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, - NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, - NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, - NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, - NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, - NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 - }; - static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) - { - return NI_USUAL_PFI_SELECT(pfi_channel); - } - static inline unsigned - NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) - { - return NI_USUAL_RTSI_SELECT(rtsi_channel); - } +enum ni_m_series_cdio_scan_begin_src { + NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, + NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, + NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, + NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, + NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, + NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, + NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, + NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, + NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, + NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 +}; +static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) +{ + return NI_USUAL_PFI_SELECT(pfi_channel); +} +static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) +{ + return NI_USUAL_RTSI_SELECT(rtsi_channel); +} /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to * change polarity. */ - static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) - { - return NI_USUAL_PFI_SELECT(pfi_channel); - } - static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) - { - return NI_USUAL_RTSI_SELECT(rtsi_channel); - } +static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) +{ + return NI_USUAL_PFI_SELECT(pfi_channel); +} +static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) +{ + return NI_USUAL_RTSI_SELECT(rtsi_channel); +} /* Bits for setting a clock source with * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ - enum ni_freq_out_clock_source_bits { - NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ - NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ - }; +enum ni_freq_out_clock_source_bits { + NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ + NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ +}; /* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ - enum amplc_dio_clock_source { - AMPLC_DIO_CLK_CLKN, /* per channel external clock - input/output pin (pin is only an - input when clock source set to this - value, otherwise it is an output) */ - AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ - AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ - AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ - AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ - AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ - AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel - (for channel 0, preceding counter - channel is channel 2 on preceding - counter subdevice, for first counter - subdevice, preceding counter - subdevice is the last counter - subdevice) */ - AMPLC_DIO_CLK_EXT /* per chip external input pin */ - }; +enum amplc_dio_clock_source { + AMPLC_DIO_CLK_CLKN, /* per channel external clock + input/output pin (pin is only an + input when clock source set to this + value, otherwise it is an output) */ + AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ + AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ + AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ + AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ + AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ + AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel + (for channel 0, preceding counter + channel is channel 2 on preceding + counter subdevice, for first counter + subdevice, preceding counter + subdevice is the last counter + subdevice) */ + AMPLC_DIO_CLK_EXT /* per chip external input pin */ +}; /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ - enum amplc_dio_gate_source { - AMPLC_DIO_GAT_VCC, /* internal high logic level */ - AMPLC_DIO_GAT_GND, /* internal low logic level */ - AMPLC_DIO_GAT_GATN, /* per channel external gate input */ - AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel - minus 2 (for channels 0 or 1, - channel minus 2 is channel 1 or 2 on - the preceding counter subdevice, for - the first counter subdevice the - preceding counter subdevice is the - last counter subdevice) */ - AMPLC_DIO_GAT_RESERVED4, - AMPLC_DIO_GAT_RESERVED5, - AMPLC_DIO_GAT_RESERVED6, - AMPLC_DIO_GAT_RESERVED7 - }; +enum amplc_dio_gate_source { + AMPLC_DIO_GAT_VCC, /* internal high logic level */ + AMPLC_DIO_GAT_GND, /* internal low logic level */ + AMPLC_DIO_GAT_GATN, /* per channel external gate input */ + AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel + minus 2 (for channels 0 or 1, + channel minus 2 is channel 1 or 2 on + the preceding counter subdevice, for + the first counter subdevice the + preceding counter subdevice is the + last counter subdevice) */ + AMPLC_DIO_GAT_RESERVED4, + AMPLC_DIO_GAT_RESERVED5, + AMPLC_DIO_GAT_RESERVED6, + AMPLC_DIO_GAT_RESERVED7 +}; #endif /* _COMEDI_H */ diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 00d8d1fd6e89..c2a32cf95a82 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -370,7 +370,8 @@ static int do_devconfig_ioctl(struct comedi_device *dev, return -ENOMEM; if (copy_from_user(aux_data, - comedi_aux_data(it.options, 0), aux_len)) { + (unsigned char __user * + )comedi_aux_data(it.options, 0), aux_len)) { vfree(aux_data); return -EFAULT; } @@ -949,7 +950,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EAGAIN; break; } - ret = s->async->inttrig(dev, s, insn->data[0]); + ret = s->async->inttrig(dev, s, data[0]); if (ret >= 0) ret = 1; break; @@ -1131,37 +1132,37 @@ static void comedi_set_subdevice_runflags(struct comedi_subdevice *s, } static int do_cmd_ioctl(struct comedi_device *dev, - struct comedi_cmd __user *cmd, void *file) + struct comedi_cmd __user *arg, void *file) { - struct comedi_cmd user_cmd; + struct comedi_cmd cmd; struct comedi_subdevice *s; struct comedi_async *async; int ret = 0; - unsigned int __user *chanlist_saver = NULL; + unsigned int __user *user_chanlist; - if (copy_from_user(&user_cmd, cmd, sizeof(struct comedi_cmd))) { + if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - chanlist_saver = user_cmd.chanlist; + user_chanlist = (unsigned int __user *)cmd.chanlist; - if (user_cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", user_cmd.subdev); + if (cmd.subdev >= dev->n_subdevices) { + DPRINTK("%d no such subdevice\n", cmd.subdev); return -ENODEV; } - s = &dev->subdevices[user_cmd.subdev]; + s = &dev->subdevices[cmd.subdev]; async = s->async; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", user_cmd.subdev); + DPRINTK("%d not valid subdevice\n", cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest || !s->async) { DPRINTK("subdevice %i does not support commands\n", - user_cmd.subdev); + cmd.subdev); return -EIO; } @@ -1179,23 +1180,22 @@ static int do_cmd_ioctl(struct comedi_device *dev, s->busy = file; /* make sure channel/gain list isn't too long */ - if (user_cmd.chanlist_len > s->len_chanlist) { + if (cmd.chanlist_len > s->len_chanlist) { DPRINTK("channel/gain list too long %u > %d\n", - user_cmd.chanlist_len, s->len_chanlist); + cmd.chanlist_len, s->len_chanlist); ret = -EINVAL; goto cleanup; } /* make sure channel/gain list isn't too short */ - if (user_cmd.chanlist_len < 1) { + if (cmd.chanlist_len < 1) { DPRINTK("channel/gain list too short %u < 1\n", - user_cmd.chanlist_len); + cmd.chanlist_len); ret = -EINVAL; goto cleanup; } - kfree(async->cmd.chanlist); - async->cmd = user_cmd; + async->cmd = cmd; async->cmd.data = NULL; /* load channel/gain list */ async->cmd.chanlist = @@ -1206,7 +1206,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist, + if (copy_from_user(async->cmd.chanlist, user_chanlist, async->cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; @@ -1226,11 +1226,11 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & TRIG_BOGUS || ret) { DPRINTK("test returned %d\n", ret); - user_cmd = async->cmd; + cmd = async->cmd; /* restore chanlist pointer before copying back */ - user_cmd.chanlist = chanlist_saver; - user_cmd.data = NULL; - if (copy_to_user(cmd, &user_cmd, sizeof(struct comedi_cmd))) { + cmd.chanlist = (unsigned int __force *)user_chanlist; + cmd.data = NULL; + if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { DPRINTK("fault writing cmd\n"); ret = -EFAULT; goto cleanup; @@ -1283,77 +1283,77 @@ cleanup: static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { - struct comedi_cmd user_cmd; + struct comedi_cmd cmd; struct comedi_subdevice *s; int ret = 0; unsigned int *chanlist = NULL; - unsigned int __user *chanlist_saver = NULL; + unsigned int __user *user_chanlist; - if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) { + if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ - chanlist_saver = user_cmd.chanlist; + user_chanlist = (unsigned int __user *)cmd.chanlist; - if (user_cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", user_cmd.subdev); + if (cmd.subdev >= dev->n_subdevices) { + DPRINTK("%d no such subdevice\n", cmd.subdev); return -ENODEV; } - s = &dev->subdevices[user_cmd.subdev]; + s = &dev->subdevices[cmd.subdev]; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", user_cmd.subdev); + DPRINTK("%d not valid subdevice\n", cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest) { DPRINTK("subdevice %i does not support commands\n", - user_cmd.subdev); + cmd.subdev); return -EIO; } /* make sure channel/gain list isn't too long */ - if (user_cmd.chanlist_len > s->len_chanlist) { + if (cmd.chanlist_len > s->len_chanlist) { DPRINTK("channel/gain list too long %d > %d\n", - user_cmd.chanlist_len, s->len_chanlist); + cmd.chanlist_len, s->len_chanlist); ret = -EINVAL; goto cleanup; } /* load channel/gain list */ - if (user_cmd.chanlist) { + if (cmd.chanlist) { chanlist = - kmalloc(user_cmd.chanlist_len * sizeof(int), GFP_KERNEL); + kmalloc(cmd.chanlist_len * sizeof(int), GFP_KERNEL); if (!chanlist) { DPRINTK("allocation failed\n"); ret = -ENOMEM; goto cleanup; } - if (copy_from_user(chanlist, user_cmd.chanlist, - user_cmd.chanlist_len * sizeof(int))) { + if (copy_from_user(chanlist, user_chanlist, + cmd.chanlist_len * sizeof(int))) { DPRINTK("fault reading chanlist\n"); ret = -EFAULT; goto cleanup; } /* make sure each element in channel/gain list is valid */ - ret = comedi_check_chanlist(s, user_cmd.chanlist_len, chanlist); + ret = comedi_check_chanlist(s, cmd.chanlist_len, chanlist); if (ret < 0) { DPRINTK("bad chanlist\n"); goto cleanup; } - user_cmd.chanlist = chanlist; + cmd.chanlist = chanlist; } - ret = s->do_cmdtest(dev, s, &user_cmd); + ret = s->do_cmdtest(dev, s, &cmd); /* restore chanlist pointer before copying back */ - user_cmd.chanlist = chanlist_saver; + cmd.chanlist = (unsigned int __force *)user_chanlist; - if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) { + if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) { DPRINTK("bad cmd address\n"); ret = -EFAULT; goto cleanup; @@ -2032,6 +2032,8 @@ static void do_become_nonbusy(struct comedi_device *dev, if (async) { comedi_reset_async_buf(async); async->inttrig = NULL; + kfree(async->cmd.chanlist); + async->cmd.chanlist = NULL; } else { dev_err(dev->class_dev, "BUG: (?) do_become_nonbusy called with async=NULL\n"); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 2c21dbd89455..1db6bfdbf13b 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -415,7 +415,6 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, new_insn.insn = INSN_BITS; new_insn.chanspec = base_bitfield_channel; new_insn.n = 2; - new_insn.data = new_data; new_insn.subdev = insn->subdev; if (insn->insn == INSN_WRITE) { diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 3eb45d46e05b..429e0d60c0a3 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -262,8 +262,10 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift, return 0; } -static inline int i8254_mm_load(void *base_address, unsigned int regshift, - unsigned int counter_number, unsigned int count, +static inline int i8254_mm_load(void __iomem *base_address, + unsigned int regshift, + unsigned int counter_number, + unsigned int count, unsigned int mode) { unsigned int byte; @@ -311,7 +313,8 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift, return ret; } -static inline int i8254_mm_read(void *base_address, unsigned int regshift, +static inline int i8254_mm_read(void __iomem *base_address, + unsigned int regshift, unsigned int counter_number) { unsigned int byte; @@ -348,7 +351,7 @@ static inline void i8254_write(unsigned long base_address, outb(byte, base_address + (counter_number << regshift)); } -static inline void i8254_mm_write(void *base_address, +static inline void i8254_mm_write(void __iomem *base_address, unsigned int regshift, unsigned int counter_number, unsigned int count) @@ -390,7 +393,7 @@ static inline int i8254_set_mode(unsigned long base_address, return 0; } -static inline int i8254_mm_set_mode(void *base_address, +static inline int i8254_mm_set_mode(void __iomem *base_address, unsigned int regshift, unsigned int counter_number, unsigned int mode) @@ -419,7 +422,7 @@ static inline int i8254_status(unsigned long base_address, return inb(base_address + (counter_number << regshift)); } -static inline int i8254_mm_status(void *base_address, +static inline int i8254_mm_status(void __iomem *base_address, unsigned int regshift, unsigned int counter_number) { diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 39a2b1eed811..d13c8c5822bf 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -31,16 +31,10 @@ Devices: [IOTech] DAQBoard/2000 (daqboard2000) Much of the functionality of this driver was determined from reading the source code for the Windows driver. -The FPGA on the board requires initialization code, which can -be loaded by comedi_config using the -i -option. The initialization code is available from http://www.comedi.org -in the comedi_nonfree_firmware tarball. - -Configuration options: - [0] - PCI bus of device (optional) - [1] - PCI slot of device (optional) - If bus/slot is not specified, the first supported - PCI device found will be used. +The FPGA on the board requires fimware, which is available from +http://www.comedi.org in the comedi_nonfree_firmware tarball. + +Configuration options: not applicable, uses PCI auto config */ /* This card was obviously never intended to leave the Windows world, @@ -117,17 +111,17 @@ Configuration options: #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/firmware.h> #include "8255.h" +#define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin" + #define PCI_VENDOR_ID_IOTECH 0x1616 #define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */ #define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */ -#define DAQBOARD2000_DAQ_SIZE 0x1002 -#define DAQBOARD2000_PLX_SIZE 0x100 - /* Initialization bits for the Serial EEPROM Control Register */ #define DAQBOARD2000_SECRProgPinHi 0x8001767e #define DAQBOARD2000_SECRProgPinLo 0x8000767e @@ -143,85 +137,56 @@ Configuration options: #define DAQBOARD2000_CPLD_INIT 0x0002 #define DAQBOARD2000_CPLD_DONE 0x0004 -/* Available ranges */ -static const struct comedi_lrange range_daqboard2000_ai = { 13, { - RANGE(-10, 10), - RANGE(-5, 5), - RANGE(-2.5, - 2.5), - RANGE(-1.25, - 1.25), - RANGE(-0.625, - 0.625), - RANGE(-0.3125, - 0.3125), - RANGE(-0.156, - 0.156), - RANGE(0, 10), - RANGE(0, 5), - RANGE(0, 2.5), - RANGE(0, 1.25), - RANGE(0, - 0.625), - RANGE(0, - 0.3125) - } -}; - -static const struct comedi_lrange range_daqboard2000_ao = { 1, { - RANGE(-10, 10) - } +static const struct comedi_lrange range_daqboard2000_ai = { + 13, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125), + BIP_RANGE(0.156), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + UNI_RANGE(0.625), + UNI_RANGE(0.3125) + } }; -struct daqboard2000_hw { - volatile u16 acqControl; /* 0x00 */ - volatile u16 acqScanListFIFO; /* 0x02 */ - volatile u32 acqPacerClockDivLow; /* 0x04 */ - - volatile u16 acqScanCounter; /* 0x08 */ - volatile u16 acqPacerClockDivHigh; /* 0x0a */ - volatile u16 acqTriggerCount; /* 0x0c */ - volatile u16 fill2; /* 0x0e */ - volatile u16 acqResultsFIFO; /* 0x10 */ - volatile u16 fill3; /* 0x12 */ - volatile u16 acqResultsShadow; /* 0x14 */ - volatile u16 fill4; /* 0x16 */ - volatile u16 acqAdcResult; /* 0x18 */ - volatile u16 fill5; /* 0x1a */ - volatile u16 dacScanCounter; /* 0x1c */ - volatile u16 fill6; /* 0x1e */ - - volatile u16 dacControl; /* 0x20 */ - volatile u16 fill7; /* 0x22 */ - volatile s16 dacFIFO; /* 0x24 */ - volatile u16 fill8[2]; /* 0x26 */ - volatile u16 dacPacerClockDiv; /* 0x2a */ - volatile u16 refDacs; /* 0x2c */ - volatile u16 fill9; /* 0x2e */ - - volatile u16 dioControl; /* 0x30 */ - volatile s16 dioP3hsioData; /* 0x32 */ - volatile u16 dioP3Control; /* 0x34 */ - volatile u16 calEepromControl; /* 0x36 */ - volatile s16 dacSetting[4]; /* 0x38 */ - volatile s16 dioP2ExpansionIO8Bit[32]; /* 0x40 */ - - volatile u16 ctrTmrControl; /* 0x80 */ - volatile u16 fill10[3]; /* 0x82 */ - volatile s16 ctrInput[4]; /* 0x88 */ - volatile u16 fill11[8]; /* 0x90 */ - volatile u16 timerDivisor[2]; /* 0xa0 */ - volatile u16 fill12[6]; /* 0xa4 */ - - volatile u16 dmaControl; /* 0xb0 */ - volatile u16 trigControl; /* 0xb2 */ - volatile u16 fill13[2]; /* 0xb4 */ - volatile u16 calEeprom; /* 0xb8 */ - volatile u16 acqDigitalMark; /* 0xba */ - volatile u16 trigDacs; /* 0xbc */ - volatile u16 fill14; /* 0xbe */ - volatile s16 dioP2ExpansionIO16Bit[32]; /* 0xc0 */ -}; +/* + * Register Memory Map + */ +#define acqControl 0x00 /* u16 */ +#define acqScanListFIFO 0x02 /* u16 */ +#define acqPacerClockDivLow 0x04 /* u32 */ +#define acqScanCounter 0x08 /* u16 */ +#define acqPacerClockDivHigh 0x0a /* u16 */ +#define acqTriggerCount 0x0c /* u16 */ +#define acqResultsFIFO 0x10 /* u16 */ +#define acqResultsShadow 0x14 /* u16 */ +#define acqAdcResult 0x18 /* u16 */ +#define dacScanCounter 0x1c /* u16 */ +#define dacControl 0x20 /* u16 */ +#define dacFIFO 0x24 /* s16 */ +#define dacPacerClockDiv 0x2a /* u16 */ +#define refDacs 0x2c /* u16 */ +#define dioControl 0x30 /* u16 */ +#define dioP3hsioData 0x32 /* s16 */ +#define dioP3Control 0x34 /* u16 */ +#define calEepromControl 0x36 /* u16 */ +#define dacSetting(x) (0x38 + (x)*2) /* s16 */ +#define dioP2ExpansionIO8Bit 0x40 /* s16 */ +#define ctrTmrControl 0x80 /* u16 */ +#define ctrInput(x) (0x88 + (x)*2) /* s16 */ +#define timerDivisor(x) (0xa0 + (x)*2) /* u16 */ +#define dmaControl 0xb0 /* u16 */ +#define trigControl 0xb2 /* u16 */ +#define calEeprom 0xb8 /* u16 */ +#define acqDigitalMark 0xba /* u16 */ +#define trigDacs 0xbc /* u16 */ +#define dioP2ExpansionIO16Bit(x) (0xc0 + (x)*2) /* s16 */ /* Scan Sequencer programming */ #define DAQBOARD2000_SeqStartScanList 0x0011 @@ -311,27 +276,23 @@ static const struct daq200_boardtype boardtypes[] = { {"ids4", DAQBOARD2000_SUBSYSTEM_IDS4}, }; -#define this_board ((const struct daq200_boardtype *)dev->board_ptr) - struct daqboard2000_private { enum { card_daqboard_2000 } card; - void *daq; + void __iomem *daq; void __iomem *plx; unsigned int ao_readback[2]; }; -#define devpriv ((struct daqboard2000_private *)dev->private) - static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; -/* udelay(4); */ - fpga->acqScanListFIFO = entry & 0x00ff; -/* udelay(4); */ - fpga->acqScanListFIFO = (entry >> 8) & 0x00ff; + /* udelay(4); */ + writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO); + /* udelay(4); */ + writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO); } static void setup_sampling(struct comedi_device *dev, int chan, int gain) @@ -372,7 +333,6 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain) /* These should be read from EEPROM */ word2 |= 0x0800; word3 |= 0xc000; -/* printk("%d %4.4x %4.4x %4.4x %4.4x\n", chan, word0, word1, word2, word3);*/ writeAcqScanListEntry(dev, word0); writeAcqScanListEntry(dev, word1); writeAcqScanListEntry(dev, word2); @@ -384,21 +344,22 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; + unsigned int val; int gain, chan, timeout; + int i; - fpga->acqControl = - DAQBOARD2000_AcqResetScanListFifo | - DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe; + writew(DAQBOARD2000_AcqResetScanListFifo | + DAQBOARD2000_AcqResetResultsFifo | + DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl); /* * If pacer clock is not set to some high value (> 10 us), we * risk multiple samples to be put into the result FIFO. */ /* 1 second, should be long enough */ - fpga->acqPacerClockDivLow = 1000000; - fpga->acqPacerClockDivHigh = 0; + writel(1000000, devpriv->daq + acqPacerClockDivLow); + writew(0, devpriv->daq + acqPacerClockDivHigh); gain = CR_RANGE(insn->chanspec); chan = CR_CHAN(insn->chanspec); @@ -410,28 +371,30 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { setup_sampling(dev, chan, gain); /* Enable reading from the scanlist FIFO */ - fpga->acqControl = DAQBOARD2000_SeqStartScanList; + writew(DAQBOARD2000_SeqStartScanList, + devpriv->daq + acqControl); for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqConfigPipeFull) break; /* udelay(2); */ } - fpga->acqControl = DAQBOARD2000_AdcPacerEnable; + writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl); for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqLogicScanning) break; /* udelay(2); */ } for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & - DAQBOARD2000_AcqResultsFIFOHasValidData) { + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqResultsFIFOHasValidData) break; - } /* udelay(2); */ } - data[i] = fpga->acqResultsFIFO; - fpga->acqControl = DAQBOARD2000_AdcPacerDisable; - fpga->acqControl = DAQBOARD2000_SeqStopScanList; + data[i] = readw(devpriv->daq + acqResultsFIFO); + writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); + writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); } return i; @@ -442,8 +405,9 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; + struct daqboard2000_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); + int i; for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; @@ -456,28 +420,39 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; + struct daqboard2000_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); - struct daqboard2000_hw *fpga = devpriv->daq; + unsigned int val; int timeout; + int i; for (i = 0; i < insn->n; i++) { +#if 0 /* - * OK, since it works OK without enabling the DAC's, let's keep - * it as simple as possible... + * OK, since it works OK without enabling the DAC's, + * let's keep it as simple as possible... */ - /* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; udelay(1000); */ - fpga->dacSetting[chan] = data[i]; + writew((chan + 2) * 0x0010 | 0x0001, + devpriv->daq + dacControl); + udelay(1000); +#endif + writew(data[i], devpriv->daq + dacSetting(chan)); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & ((chan + 1) * 0x0010)) == 0) break; /* udelay(2); */ } devpriv->ao_readback[chan] = data[i]; +#if 0 /* - * Since we never enabled the DAC's, we don't need to disable it... - * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; udelay(1000); + * Since we never enabled the DAC's, we don't need + * to disable it... */ + writew((chan + 2) * 0x0010 | 0x0000, + devpriv->daq + dacControl); + udelay(1000); +#endif } return i; @@ -485,7 +460,8 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, static void daqboard2000_resetLocalBus(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_resetLocalBus\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); @@ -494,7 +470,8 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev) static void daqboard2000_reloadPLX(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_reloadPLX\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); @@ -505,7 +482,8 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev) static void daqboard2000_pulseProgPin(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_pulseProgPin 1\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); @@ -514,6 +492,7 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev) static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) { + struct daqboard2000_private *devpriv = dev->private; int result = 0; int i; int cpld; @@ -533,6 +512,7 @@ static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) { + struct daqboard2000_private *devpriv = dev->private; int result = 0; udelay(10); @@ -545,41 +525,29 @@ static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) } static int initialize_daqboard2000(struct comedi_device *dev, - unsigned char *cpld_array, int len) + const u8 *cpld_array, size_t len) { + struct daqboard2000_private *devpriv = dev->private; int result = -EIO; /* Read the serial EEPROM control register */ int secr; int retry; - int i; + size_t i; /* Check to make sure the serial eeprom is present on the board */ secr = readl(devpriv->plx + 0x6c); - if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "no serial eeprom\n"); -#endif + if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) return -EIO; - } for (retry = 0; retry < 3; retry++) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "Programming EEPROM try %x\n", retry); -#endif - daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); daqboard2000_pulseProgPin(dev); if (daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) { for (i = 0; i < len; i++) { - if (cpld_array[i] == 0xff - && cpld_array[i + 1] == 0x20) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, - "Preamble found at %d\n", i); -#endif + if (cpld_array[i] == 0xff && + cpld_array[i + 1] == 0x20) break; - } } for (; i < len; i += 2) { int data = @@ -588,9 +556,6 @@ static int initialize_daqboard2000(struct comedi_device *dev, break; } if (i >= len) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "Programmed\n"); -#endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); result = 0; @@ -601,28 +566,45 @@ static int initialize_daqboard2000(struct comedi_device *dev, return result; } +static int daqboard2000_upload_firmware(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, DAQBOARD2000_FIRMWARE, &pcidev->dev); + if (ret) + return ret; + + ret = initialize_daqboard2000(dev, fw->data, fw->size); + release_firmware(fw); + + return ret; +} + static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/ } static void daqboard2000_adcDisarm(struct comedi_device *dev) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; /* Disable hardware triggers */ udelay(2); - fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable; + writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable, + devpriv->daq + trigControl); udelay(2); - fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable; + writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable, + devpriv->daq + trigControl); /* Stop the scan list FIFO from loading the configuration pipe */ udelay(2); - fpga->acqControl = DAQBOARD2000_SeqStopScanList; + writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); /* Stop the pacer clock */ udelay(2); - fpga->acqControl = DAQBOARD2000_AdcPacerDisable; + writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); /* Stop the input dma (abort channel 1) */ daqboard2000_adcStopDmaTransfer(dev); @@ -630,41 +612,39 @@ static void daqboard2000_adcDisarm(struct comedi_device *dev) static void daqboard2000_activateReferenceDacs(struct comedi_device *dev) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; + unsigned int val; int timeout; /* Set the + reference dac value in the FPGA */ - fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect; + writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } -/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/ /* Set the - reference dac value in the FPGA */ - fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect; + writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } -/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/ } static void daqboard2000_initializeCtrs(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_initializeCtrs\n");*/ } static void daqboard2000_initializeTmrs(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_initializeTmrs\n");*/ } static void daqboard2000_dacDisarm(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_dacDisarm\n");*/ } static void daqboard2000_initializeAdc(struct comedi_device *dev) @@ -680,92 +660,66 @@ static void daqboard2000_initializeDac(struct comedi_device *dev) daqboard2000_dacDisarm(dev); } -/* -The test command, REMOVE!!: - -rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages -*/ - static int daqboard2000_8255_cb(int dir, int port, int data, unsigned long ioaddr) { - int result = 0; + void __iomem *mmio_base = (void __iomem *)ioaddr; + if (dir) { - writew(data, ((void *)ioaddr) + port * 2); - result = 0; + writew(data, mmio_base + port * 2); + return 0; } else { - result = readw(((void *)ioaddr) + port * 2); + return readw(mmio_base + port * 2); } -/* - printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n", - arg, dir, port, data, result); -*/ - return result; } -static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) +static const void *daqboard2000_find_boardinfo(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; + const struct daq200_boardtype *board; int i; - for_each_pci_dev(pcidev) { - if (bus || slot) { - if (bus != pcidev->bus->number || - slot != PCI_SLOT(pcidev->devfn)) - continue; - } - if (pcidev->vendor != PCI_VENDOR_ID_IOTECH || - pcidev->device != 0x0409 || - pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH) - continue; - - for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { - if (boardtypes[i].id != pcidev->subsystem_device) - continue; - dev->board_ptr = boardtypes + i; - return pcidev; - } + if (pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH) + return NULL; + + for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { + board = &boardtypes[i]; + if (pcidev->subsystem_device == board->id) + return board; } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); return NULL; } -static int daqboard2000_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int daqboard2000_attach_pci(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev; + const struct daq200_boardtype *board; + struct daqboard2000_private *devpriv; struct comedi_subdevice *s; - resource_size_t pci_base; - void *aux_data; - unsigned int aux_len; int result; - result = alloc_private(dev, sizeof(struct daqboard2000_private)); + comedi_set_hw_dev(dev, &pcidev->dev); + + board = daqboard2000_find_boardinfo(dev, pcidev); + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + result = alloc_private(dev, sizeof(*devpriv)); if (result < 0) return -ENOMEM; + devpriv = dev->private; - pcidev = daqboard2000_find_pci_dev(dev, it); - if (!pcidev) - return -EIO; - comedi_set_hw_dev(dev, &pcidev->dev); - - result = comedi_pci_enable(pcidev, "daqboard2000"); - if (result < 0) { - dev_err(dev->class_dev, - "failed to enable PCI device and request regions\n"); - return -EIO; - } + result = comedi_pci_enable(pcidev, dev->driver->driver_name); + if (result < 0) + return result; dev->iobase = 1; /* the "detach" needs this */ - pci_base = pci_resource_start(pcidev, 0); - devpriv->plx = ioremap(pci_base, DAQBOARD2000_PLX_SIZE); - pci_base = pci_resource_start(pcidev, 2); - devpriv->daq = ioremap(pci_base, DAQBOARD2000_DAQ_SIZE); + devpriv->plx = ioremap(pci_resource_start(pcidev, 0), + pci_resource_len(pcidev, 0)); + devpriv->daq = ioremap(pci_resource_start(pcidev, 2), + pci_resource_len(pcidev, 2)); if (!devpriv->plx || !devpriv->daq) return -ENOMEM; @@ -775,34 +729,12 @@ static int daqboard2000_attach(struct comedi_device *dev, readl(devpriv->plx + 0x6c); - /* - u8 interrupt; - Windows code does restore interrupts, but since we don't use them... - pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); - printk("Interrupt before is: %x\n", interrupt); - */ - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - - if (aux_data && aux_len) { - result = initialize_daqboard2000(dev, aux_data, aux_len); - } else { - dev_dbg(dev->class_dev, - "no FPGA initialization code, aborting\n"); - result = -EIO; - } + result = daqboard2000_upload_firmware(dev); if (result < 0) - goto out; + return result; + daqboard2000_initializeAdc(dev); daqboard2000_initializeDac(dev); - /* - Windows code does restore interrupts, but since we don't use them... - pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); - printk("Interrupt after is: %x\n", interrupt); - */ - - dev->board_name = this_board->name; s = &dev->subdevices[0]; /* ai subdevice */ @@ -821,19 +753,24 @@ static int daqboard2000_attach(struct comedi_device *dev, s->maxdata = 0xffff; s->insn_read = daqboard2000_ao_insn_read; s->insn_write = daqboard2000_ao_insn_write; - s->range_table = &range_daqboard2000_ao; + s->range_table = &range_bipolar10; s = &dev->subdevices[2]; result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - (unsigned long)(devpriv->daq + 0x40)); + (unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit)); + if (result) + return result; -out: - return result; + dev_info(dev->class_dev, "%s: %s attached\n", + dev->driver->driver_name, dev->board_name); + + return 0; } static void daqboard2000_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct daqboard2000_private *devpriv = dev->private; if (dev->subdevices) subdev_8255_cleanup(dev, &dev->subdevices[2]); @@ -855,7 +792,7 @@ static void daqboard2000_detach(struct comedi_device *dev) static struct comedi_driver daqboard2000_driver = { .driver_name = "daqboard2000", .module = THIS_MODULE, - .attach = daqboard2000_attach, + .attach_pci = daqboard2000_attach_pci, .detach = daqboard2000_detach, }; @@ -887,3 +824,4 @@ module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(DAQBOARD2000_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2a38915c69e8..744376a49d08 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -558,7 +558,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, /* utility function that suggests a dma transfer size in bytes */ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, - struct comedi_cmd cmd) + const struct comedi_cmd *cmd) { unsigned int size; unsigned int freq; @@ -571,16 +571,16 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, /* otherwise, we are relying on dma terminal count interrupt, * so pick a reasonable size */ - if (cmd.convert_src == TRIG_TIMER) - freq = 1000000000 / cmd.convert_arg; - else if (cmd.scan_begin_src == TRIG_TIMER) - freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len; + if (cmd->convert_src == TRIG_TIMER) + freq = 1000000000 / cmd->convert_arg; + else if (cmd->scan_begin_src == TRIG_TIMER) + freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len; /* return some default value */ else freq = 0xffffffff; - if (cmd.flags & TRIG_WAKE_EOS) { - size = sample_size * cmd.chanlist_len; + if (cmd->flags & TRIG_WAKE_EOS) { + size = sample_size * cmd->chanlist_len; } else { /* make buffer fill in no more than 1/3 second */ size = (freq / 3) * sample_size; @@ -592,7 +592,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, else if (size < sample_size) size = sample_size; - if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) + if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) size = devpriv->adc_byte_count; return size; @@ -685,7 +685,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) set_dma_addr(devpriv->dma_chan, devpriv->dma_buffer_addr[devpriv->current_buffer]); /* set appropriate size of transfer */ - devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd); + devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd); set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); release_dma_lock(flags); diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 5aca8fbdc246..711d4e243b88 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -958,14 +958,14 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, } /* returns appropriate bits for control register a, depending on command */ -static int control_a_bits(struct comedi_cmd cmd) +static int control_a_bits(const struct comedi_cmd *cmd) { int control_a; control_a = FFEN; /* enable fifo */ - if (cmd.stop_src == TRIG_EXT) + if (cmd->stop_src == TRIG_EXT) control_a |= ATEN; - switch (cmd.start_src) { + switch (cmd->start_src) { case TRIG_EXT: control_a |= TGEN | CGSL; break; @@ -980,7 +980,7 @@ static int control_a_bits(struct comedi_cmd cmd) } /* returns appropriate bits for control register c, depending on command */ -static int control_c_bits(struct comedi_cmd cmd) +static int control_c_bits(const struct comedi_cmd *cmd) { int control_c; int aref; @@ -988,18 +988,18 @@ static int control_c_bits(struct comedi_cmd cmd) /* set clock source to internal or external, select analog reference, * select unipolar / bipolar */ - aref = CR_AREF(cmd.chanlist[0]); + aref = CR_AREF(cmd->chanlist[0]); control_c = UQEN; /* enable upper qram addresses */ if (aref != AREF_DIFF) control_c |= SD; if (aref == AREF_COMMON) control_c |= CMEN; /* if a unipolar range was selected */ - if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR) + if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR) control_c |= UB; - switch (cmd.scan_begin_src) { + switch (cmd->scan_begin_src) { case TRIG_FOLLOW: /* not in burst mode */ - switch (cmd.convert_src) { + switch (cmd->convert_src) { case TRIG_TIMER: /* trig on cascaded counters */ control_c |= IPCLK; @@ -1047,29 +1047,33 @@ static int das1800_set_frequency(struct comedi_device *dev) } /* sets up counters */ -static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) +static int setup_counters(struct comedi_device *dev, + const struct comedi_cmd *cmd) { + unsigned int period; + /* setup cascaded counters for conversion/scan frequency */ - switch (cmd.scan_begin_src) { + switch (cmd->scan_begin_src) { case TRIG_FOLLOW: /* not in burst mode */ - if (cmd.convert_src == TRIG_TIMER) { + if (cmd->convert_src == TRIG_TIMER) { /* set conversion frequency */ + period = cmd->convert_arg; i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd.convert_arg), - cmd. - flags & TRIG_ROUND_MASK); + &devpriv->divisor1, + &devpriv->divisor2, + &period, + cmd->flags & + TRIG_ROUND_MASK); if (das1800_set_frequency(dev) < 0) return -1; } break; case TRIG_TIMER: /* in burst mode */ /* set scan frequency */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd.scan_begin_arg), - cmd.flags & TRIG_ROUND_MASK); + period = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1, + &devpriv->divisor2, &period, + cmd->flags & TRIG_ROUND_MASK); if (das1800_set_frequency(dev) < 0) return -1; break; @@ -1078,7 +1082,7 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) } /* setup counter 0 for 'about triggering' */ - if (cmd.stop_src == TRIG_EXT) { + if (cmd->stop_src == TRIG_EXT) { /* load counter 0 in mode 0 */ i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0); } @@ -1087,7 +1091,7 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd) } /* utility function that suggests a dma transfer size based on the conversion period 'ns' */ -static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) +static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) { unsigned int size = DMA_BUF_SIZE; static const int sample_size = 2; /* size in bytes of one sample from board */ @@ -1125,7 +1129,7 @@ static unsigned int suggest_transfer_size(struct comedi_cmd *cmd) } /* sets up dma */ -static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd) +static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) { unsigned long lock_flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; @@ -1134,7 +1138,7 @@ static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd) return; /* determine a reasonable dma transfer size */ - devpriv->dma_transfer_size = suggest_transfer_size(&cmd); + devpriv->dma_transfer_size = suggest_transfer_size(cmd); lock_flags = claim_dma_lock(); disable_dma(devpriv->dma0); /* clear flip-flop to make sure 2-byte registers for @@ -1163,14 +1167,15 @@ static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd) } /* programs channel/gain list into card */ -static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd) +static void program_chanlist(struct comedi_device *dev, + const struct comedi_cmd *cmd) { int i, n, chan_range; unsigned long irq_flags; const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */ const int range_bitshift = 8; - n = cmd.chanlist_len; + n = cmd->chanlist_len; /* spinlock protects indirect addressing */ spin_lock_irqsave(&dev->spinlock, irq_flags); outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ @@ -1178,9 +1183,9 @@ static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd) /* make channel / gain list */ for (i = 0; i < n; i++) { chan_range = - CR_CHAN(cmd. - chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) & - range_mask) << range_bitshift); + CR_CHAN(cmd->chanlist[i]) | + ((CR_RANGE(cmd->chanlist[i]) & range_mask) << + range_bitshift); outw(chan_range, dev->iobase + DAS1800_QRAM); } outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ @@ -1196,7 +1201,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, int ret; int control_a, control_c; struct comedi_async *async = s->async; - struct comedi_cmd cmd = async->cmd; + const struct comedi_cmd *cmd = &async->cmd; if (!dev->irq) { comedi_error(dev, @@ -1206,12 +1211,12 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* disable dma on TRIG_WAKE_EOS, or TRIG_RT * (because dma in handler is unsafe at hard real-time priority) */ - if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) + if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) devpriv->irq_dma_bits &= ~DMA_ENABLED; else devpriv->irq_dma_bits |= devpriv->dma_bits; /* interrupt on end of conversion for TRIG_WAKE_EOS */ - if (cmd.flags & TRIG_WAKE_EOS) { + if (cmd->flags & TRIG_WAKE_EOS) { /* interrupt fifo not empty */ devpriv->irq_dma_bits &= ~FIMD; } else { @@ -1219,8 +1224,8 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, devpriv->irq_dma_bits |= FIMD; } /* determine how many conversions we need */ - if (cmd.stop_src == TRIG_COUNT) - devpriv->count = cmd.stop_arg * cmd.chanlist_len; + if (cmd->stop_src == TRIG_COUNT) + devpriv->count = cmd->stop_arg * cmd->chanlist_len; das1800_cancel(dev, s); @@ -1240,9 +1245,9 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* set conversion rate and length for burst mode */ if (control_c & BMDE) { /* program conversion period with number of microseconds minus 1 */ - outb(cmd.convert_arg / 1000 - 1, + outb(cmd->convert_arg / 1000 - 1, dev->iobase + DAS1800_BURST_RATE); - outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); + outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); } outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */ outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */ diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index c68c407feb56..2ce0b14af589 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -41,22 +41,14 @@ Configuration options: If bus/slot is not specified, the first available PCI device will be used. - -The 2600 requires a firmware upload, which can be accomplished -using the -i or --init-data option of comedi_config. -The firmware can be -found in the comedi_nonfree_firmware tarball available -from http://www.comedi.org - */ #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/firmware.h> #include "../comedidev.h" -/*#include "me2600_fw.h" */ - -#define ME_DRIVER_NAME "me_daq" +#define ME2600_FIRMWARE "me2600_firmware.bin" #define PCI_VENDOR_ID_MEILHAUS 0x1402 #define ME2000_DEVICE_ID 0x2000 @@ -198,8 +190,7 @@ struct me_board { static const struct me_board me_boards[] = { { - /* -- ME-2600i -- */ - .name = ME_DRIVER_NAME, + .name = "me-2600i", .device_id = ME2600_DEVICE_ID, /* Analog Output */ .ao_channel_nbr = 4, @@ -214,8 +205,7 @@ static const struct me_board me_boards[] = { .dio_channel_nbr = 32, }, { - /* -- ME-2000i -- */ - .name = ME_DRIVER_NAME, + .name = "me-2000i", .device_id = ME2000_DEVICE_ID, /* Analog Output */ .ao_channel_nbr = 0, @@ -524,8 +514,7 @@ static int me_ao_insn_read(struct comedi_device *dev, /* Xilinx firmware download for card: ME-2600i */ static int me2600_xilinx_download(struct comedi_device *dev, - unsigned char *me2600_firmware, - unsigned int length) + const u8 *data, size_t size) { unsigned int value; unsigned int file_length; @@ -552,19 +541,20 @@ static int me2600_xilinx_download(struct comedi_device *dev, * Byte 8-11: date * Byte 12-15: reserved */ - if (length < 16) + if (size < 16) return -EINVAL; - file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) + - (((unsigned int)me2600_firmware[1] & 0xff) << 16) + - (((unsigned int)me2600_firmware[2] & 0xff) << 8) + - ((unsigned int)me2600_firmware[3] & 0xff); + + file_length = (((unsigned int)data[0] & 0xff) << 24) + + (((unsigned int)data[1] & 0xff) << 16) + + (((unsigned int)data[2] & 0xff) << 8) + + ((unsigned int)data[3] & 0xff); /* * Loop for writing firmware byte by byte to xilinx * Firmware data start at offfset 16 */ for (i = 0; i < file_length; i++) - writeb((me2600_firmware[16 + i] & 0xff), + writeb((data[16 + i] & 0xff), dev_private->me_regbase + 0x0); /* Write 5 dummy values to xilinx */ @@ -590,6 +580,22 @@ static int me2600_xilinx_download(struct comedi_device *dev, return 0; } +static int me2600_upload_firmware(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, ME2600_FIRMWARE, &pcidev->dev); + if (ret) + return ret; + + ret = me2600_xilinx_download(dev, fw->data, fw->size); + release_firmware(fw); + + return ret; +} + /* Reset device */ static int me_reset(struct comedi_device *dev) { @@ -607,44 +613,24 @@ static int me_reset(struct comedi_device *dev) return 0; } -static struct pci_dev *me_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) +static const void *me_find_boardinfo(struct comedi_device *dev, + struct pci_dev *pcidev) { const struct me_board *board; - struct pci_dev *pcidev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; int i; - for_each_pci_dev(pcidev) { - if (bus || slot) { - if (pcidev->bus->number != bus || - PCI_SLOT(pcidev->devfn) != slot) - continue; - } - if (pcidev->vendor != PCI_VENDOR_ID_MEILHAUS) - continue; - - for (i = 0; i < ARRAY_SIZE(me_boards); i++) { - board = &me_boards[i]; - if (board->device_id != pcidev->device) - continue; - - dev->board_ptr = board; - return pcidev; - } + for (i = 0; i < ARRAY_SIZE(me_boards); i++) { + board = &me_boards[i]; + if (board->device_id == pcidev->device) + return board; } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); return NULL; } -static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev) { - struct pci_dev *pci_device; + const struct me_board *board; struct comedi_subdevice *s; - struct me_board *board; resource_size_t plx_regbase_tmp; unsigned long plx_regbase_size_tmp; resource_size_t me_regbase_tmp; @@ -654,29 +640,28 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) resource_size_t regbase_tmp; int result, error; + comedi_set_hw_dev(dev, &pcidev->dev); + + board = me_find_boardinfo(dev, pcidev); + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + /* Allocate private memory */ if (alloc_private(dev, sizeof(struct me_private_data)) < 0) return -ENOMEM; - pci_device = me_find_pci_dev(dev, it); - if (!pci_device) - return -EIO; - comedi_set_hw_dev(dev, &pci_device->dev); - board = (struct me_board *)dev->board_ptr; - /* Enable PCI device and request PCI regions */ - if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) { + if (comedi_pci_enable(pcidev, dev->board_name) < 0) { printk(KERN_ERR "comedi%d: Failed to enable PCI device and " "request regions\n", dev->minor); return -EIO; } - /* Set data in device structure */ - dev->board_name = board->name; - /* Read PLX register base address [PCI_BASE_ADDRESS #0]. */ - plx_regbase_tmp = pci_resource_start(pci_device, 0); - plx_regbase_size_tmp = pci_resource_len(pci_device, 0); + plx_regbase_tmp = pci_resource_start(pcidev, 0); + plx_regbase_size_tmp = pci_resource_len(pcidev, 0); dev_private->plx_regbase = ioremap(plx_regbase_tmp, plx_regbase_size_tmp); dev_private->plx_regbase_size = plx_regbase_size_tmp; @@ -687,8 +672,8 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Read Swap base address [PCI_BASE_ADDRESS #5]. */ - swap_regbase_tmp = pci_resource_start(pci_device, 5); - swap_regbase_size_tmp = pci_resource_len(pci_device, 5); + swap_regbase_tmp = pci_resource_start(pcidev, 5); + swap_regbase_size_tmp = pci_resource_len(pcidev, 5); if (!swap_regbase_tmp) printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor); @@ -702,20 +687,20 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) plx_regbase_tmp = swap_regbase_tmp; swap_regbase_tmp = regbase_tmp; - result = pci_write_config_dword(pci_device, + result = pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, plx_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) return -EIO; - result = pci_write_config_dword(pci_device, + result = pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_5, swap_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) return -EIO; } else { plx_regbase_tmp -= 0x80; - result = pci_write_config_dword(pci_device, + result = pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, plx_regbase_tmp); if (result != PCIBIOS_SUCCESSFUL) @@ -726,8 +711,8 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */ - me_regbase_tmp = pci_resource_start(pci_device, 2); - me_regbase_size_tmp = pci_resource_len(pci_device, 2); + me_regbase_tmp = pci_resource_start(pcidev, 2); + me_regbase_size_tmp = pci_resource_len(pcidev, 2); dev_private->me_regbase_size = me_regbase_size_tmp; dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp); if (!dev_private->me_regbase) { @@ -735,23 +720,13 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->minor); return -ENOMEM; } + /* Download firmware and reset card */ if (board->device_id == ME2600_DEVICE_ID) { - unsigned char *aux_data; - int aux_len; - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - - if (!aux_data || aux_len < 1) { - comedi_error(dev, "You must provide me2600 firmware " - "using the --init-data option of " - "comedi_config"); - return -EINVAL; - } - me2600_xilinx_download(dev, aux_data, aux_len); + result = me2600_upload_firmware(dev); + if (result < 0) + return result; } - me_reset(dev); error = comedi_alloc_subdevices(dev, 3); @@ -791,8 +766,9 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_config = me_dio_insn_config; s->io_bits = 0; - printk(KERN_INFO "comedi%d: " ME_DRIVER_NAME " attached.\n", - dev->minor); + dev_info(dev->class_dev, "%s: %s attached\n", + dev->driver->driver_name, dev->board_name); + return 0; } @@ -818,7 +794,7 @@ static void me_detach(struct comedi_device *dev) static struct comedi_driver me_daq_driver = { .driver_name = "me_daq", .module = THIS_MODULE, - .attach = me_attach, + .attach_pci = me_attach_pci, .detach = me_detach, }; @@ -851,3 +827,4 @@ module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(ME2600_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 295ddbb4d586..d534e63d886e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -206,6 +206,13 @@ NI manuals: #define INIT_A1_BITS 0x70 #define COUNTER_B_BASE_REG 0x18 +enum scan_mode { + MODE_SINGLE_CHAN, + MODE_SINGLE_CHAN_INTERVAL, + MODE_MULT_CHAN_UP, + MODE_MULT_CHAN_DOWN, +}; + static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static irqreturn_t labpc_interrupt(int irq, void *d); static int labpc_drain_fifo(struct comedi_device *dev); @@ -236,9 +243,10 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd); +static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, + enum scan_mode scan_mode); #ifdef CONFIG_ISA_DMA_API -static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd); +static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd); #endif static int labpc_dio_mem_callback(int dir, int port, int data, unsigned long arg); @@ -254,13 +262,6 @@ static int labpc_eeprom_write(struct comedi_device *dev, static void write_caldac(struct comedi_device *dev, unsigned int channel, unsigned int value); -enum scan_mode { - MODE_SINGLE_CHAN, - MODE_SINGLE_CHAN_INTERVAL, - MODE_MULT_CHAN_UP, - MODE_MULT_CHAN_DOWN, -}; - /* analog input ranges */ #define NUM_LABPC_PLUS_AI_RANGES 16 /* indicates unipolar ranges */ @@ -409,12 +410,12 @@ static inline void labpc_outb(unsigned int byte, unsigned long address) static inline unsigned int labpc_readb(unsigned long address) { - return readb((void *)address); + return readb((void __iomem *)address); } static inline void labpc_writeb(unsigned int byte, unsigned long address) { - writeb(byte, (void *)address); + writeb(byte, (void __iomem *)address); } static const struct labpc_board_struct labpc_boards[] = { @@ -494,8 +495,8 @@ static inline int labpc_counter_load(struct comedi_device *dev, unsigned int count, unsigned int mode) { if (thisboard->memory_mapped_io) - return i8254_mm_load((void *)base_address, 0, counter_number, - count, mode); + return i8254_mm_load((void __iomem *)base_address, 0, + counter_number, count, mode); else return i8254_load(base_address, 0, counter_number, count, mode); } @@ -839,15 +840,14 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) } static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, - const struct comedi_cmd *cmd) + const struct comedi_cmd *cmd, + enum scan_mode mode) { - int mode, channel, range, aref, i; + int channel, range, aref, i; if (cmd->chanlist == NULL) return 0; - mode = labpc_ai_scan_mode(cmd); - if (mode == MODE_SINGLE_CHAN) return 0; @@ -911,9 +911,10 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, return 0; } -static int labpc_use_continuous_mode(const struct comedi_cmd *cmd) +static int labpc_use_continuous_mode(const struct comedi_cmd *cmd, + enum scan_mode mode) { - if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN) + if (mode == MODE_SINGLE_CHAN) return 1; if (cmd->scan_begin_src == TRIG_FOLLOW) @@ -922,24 +923,25 @@ static int labpc_use_continuous_mode(const struct comedi_cmd *cmd) return 0; } -static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd) +static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd, + enum scan_mode mode) { if (cmd->convert_src != TRIG_TIMER) return 0; - if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && - cmd->scan_begin_src == TRIG_TIMER) + if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) return cmd->scan_begin_arg; return cmd->convert_arg; } -static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns) +static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, + enum scan_mode mode, unsigned int ns) { if (cmd->convert_src != TRIG_TIMER) return; - if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) { cmd->scan_begin_arg = ns; if (cmd->convert_arg > cmd->scan_begin_arg) @@ -948,25 +950,25 @@ static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns) cmd->convert_arg = ns; } -static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd) +static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd, + enum scan_mode mode) { if (cmd->scan_begin_src != TRIG_TIMER) return 0; - if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && - cmd->convert_src == TRIG_TIMER) + if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) return 0; return cmd->scan_begin_arg; } -static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns) +static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, + enum scan_mode mode, unsigned int ns) { if (cmd->scan_begin_src != TRIG_TIMER) return; - if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && - cmd->convert_src == TRIG_TIMER) + if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) return; cmd->scan_begin_arg = ns; @@ -978,6 +980,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp, tmp2; int stop_mask; + enum scan_mode mode; /* step 1: make sure trigger sources are trivially valid */ @@ -1099,14 +1102,15 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, tmp = cmd->convert_arg; tmp2 = cmd->scan_begin_arg; - labpc_adc_timing(dev, cmd); + mode = labpc_ai_scan_mode(cmd); + labpc_adc_timing(dev, cmd, mode); if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg) err++; if (err) return 4; - if (labpc_ai_chanlist_invalid(dev, cmd)) + if (labpc_ai_chanlist_invalid(dev, cmd, mode)) return 5; return 0; @@ -1122,6 +1126,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; enum transfer_type xfer; + enum scan_mode mode; unsigned long flags; if (!dev->irq) { @@ -1187,6 +1192,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } else xfer = fifo_not_empty_transfer; devpriv->current_transfer = xfer; + mode = labpc_ai_scan_mode(cmd); /* setup command6 register for 1200 boards */ if (thisboard->register_layout == labpc_1200_layout) { @@ -1211,7 +1217,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else devpriv->command6_bits &= ~A1_INTR_EN_BIT; /* are we scanning up or down through channels? */ - if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) + if (mode == MODE_MULT_CHAN_UP) devpriv->command6_bits |= ADC_SCAN_UP_BIT; else devpriv->command6_bits &= ~ADC_SCAN_UP_BIT; @@ -1222,19 +1228,18 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* setup channel list, etc (command1 register) */ devpriv->command1_bits = 0; - if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) + if (mode == MODE_MULT_CHAN_UP) channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); else channel = CR_CHAN(cmd->chanlist[0]); /* munge channel bits for differential / scan disabled mode */ - if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) + if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF) channel *= 2; devpriv->command1_bits |= ADC_CHAN_BITS(channel); devpriv->command1_bits |= thisboard->ai_range_code[range]; devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); /* manual says to set scan enable bit on second pass */ - if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP || - labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) { + if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) { devpriv->command1_bits |= ADC_SCAN_EN_BIT; /* need a brief delay before enabling scan, or scan * list will get screwed when you switch @@ -1249,7 +1254,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; /* XXX should discard first scan when using interval scanning * since manual says it is not synced with scan clock */ - if (labpc_use_continuous_mode(cmd) == 0) { + if (labpc_use_continuous_mode(cmd, mode) == 0) { devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; if (cmd->scan_begin_src == TRIG_EXT) devpriv->command4_bits |= EXT_SCAN_EN_BIT; @@ -1267,7 +1272,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { /* set up pacing */ - labpc_adc_timing(dev, cmd); + labpc_adc_timing(dev, cmd, mode); /* load counter b0 in mode 3 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 0, devpriv->divisor_b0, 3); @@ -1277,7 +1282,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } } /* set up conversion pacing */ - if (labpc_ai_convert_period(cmd)) { + if (labpc_ai_convert_period(cmd, mode)) { /* load counter a0 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, 0, devpriv->divisor_a0, 2); @@ -1290,7 +1295,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dev->iobase + COUNTER_A_CONTROL_REG); /* set up scan pacing */ - if (labpc_ai_scan_period(cmd)) { + if (labpc_ai_scan_period(cmd, mode)) { /* load counter b1 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 1, devpriv->divisor_b1, 2); @@ -1313,7 +1318,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer)); /* set appropriate size of transfer */ - devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd); + devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); if (cmd->stop_src == TRIG_COUNT && devpriv->count * sample_size < devpriv->dma_transfer_size) { devpriv->dma_transfer_size = @@ -1766,13 +1771,13 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, #ifdef CONFIG_ISA_DMA_API /* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd) +static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) { unsigned int size; unsigned int freq; - if (cmd.convert_src == TRIG_TIMER) - freq = 1000000000 / cmd.convert_arg; + if (cmd->convert_src == TRIG_TIMER) + freq = 1000000000 / cmd->convert_arg; /* return some default value */ else freq = 0xffffffff; @@ -1791,24 +1796,29 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd) #endif /* figures out what counter values to use based on command */ -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) +static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, + enum scan_mode mode) { /* max value for 16 bit counter in mode 2 */ const int max_counter_value = 0x10000; /* min value for 16 bit counter in mode 2 */ const int min_counter_value = 2; unsigned int base_period; + unsigned int scan_period; + unsigned int convert_period; /* * if both convert and scan triggers are TRIG_TIMER, then they * both rely on counter b0 */ - if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) { + convert_period = labpc_ai_convert_period(cmd, mode); + scan_period = labpc_ai_scan_period(cmd, mode); + if (convert_period && scan_period) { /* * pick the lowest b0 divisor value we can (for maximum input * clock speed on convert and scan counters) */ - devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) / + devpriv->divisor_b0 = (scan_period - 1) / (LABPC_TIMER_BASE * max_counter_value) + 1; if (devpriv->divisor_b0 < min_counter_value) devpriv->divisor_b0 = min_counter_value; @@ -1822,25 +1832,19 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) default: case TRIG_ROUND_NEAREST: devpriv->divisor_a0 = - (labpc_ai_convert_period(cmd) + - (base_period / 2)) / base_period; + (convert_period + (base_period / 2)) / base_period; devpriv->divisor_b1 = - (labpc_ai_scan_period(cmd) + - (base_period / 2)) / base_period; + (scan_period + (base_period / 2)) / base_period; break; case TRIG_ROUND_UP: devpriv->divisor_a0 = - (labpc_ai_convert_period(cmd) + (base_period - - 1)) / base_period; + (convert_period + (base_period - 1)) / base_period; devpriv->divisor_b1 = - (labpc_ai_scan_period(cmd) + (base_period - - 1)) / base_period; + (scan_period + (base_period - 1)) / base_period; break; case TRIG_ROUND_DOWN: - devpriv->divisor_a0 = - labpc_ai_convert_period(cmd) / base_period; - devpriv->divisor_b1 = - labpc_ai_scan_period(cmd) / base_period; + devpriv->divisor_a0 = convert_period / base_period; + devpriv->divisor_b1 = scan_period / base_period; break; } /* make sure a0 and b1 values are acceptable */ @@ -1853,18 +1857,15 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) if (devpriv->divisor_b1 > max_counter_value) devpriv->divisor_b1 = max_counter_value; /* write corrected timings to command */ - labpc_set_ai_convert_period(cmd, + labpc_set_ai_convert_period(cmd, mode, base_period * devpriv->divisor_a0); - labpc_set_ai_scan_period(cmd, + labpc_set_ai_scan_period(cmd, mode, base_period * devpriv->divisor_b1); /* * if only one TRIG_TIMER is used, we can employ the generic * cascaded timing functions */ - } else if (labpc_ai_scan_period(cmd)) { - unsigned int scan_period; - - scan_period = labpc_ai_scan_period(cmd); + } else if (scan_period) { /* * calculate cascaded counter values * that give desired scan timing @@ -1874,11 +1875,8 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) &(devpriv->divisor_b0), &scan_period, cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_scan_period(cmd, scan_period); - } else if (labpc_ai_convert_period(cmd)) { - unsigned int convert_period; - - convert_period = labpc_ai_convert_period(cmd); + labpc_set_ai_scan_period(cmd, mode, scan_period); + } else if (convert_period) { /* * calculate cascaded counter values * that give desired conversion timing @@ -1888,7 +1886,7 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) &(devpriv->divisor_b0), &convert_period, cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_convert_period(cmd, convert_period); + labpc_set_ai_convert_period(cmd, mode, convert_period); } } @@ -1896,10 +1894,10 @@ static int labpc_dio_mem_callback(int dir, int port, int data, unsigned long iobase) { if (dir) { - writeb(data, (void *)(iobase + port)); + writeb(data, (void __iomem *)(iobase + port)); return 0; } else { - return readb((void *)(iobase + port)); + return readb((void __iomem *)(iobase + port)); } } diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 58f5922d6e4c..d0e4844e5248 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -964,7 +964,7 @@ static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) /* cmdtest tests a particular command to see if it is valid. Using the cmdtest ioctl, a user can create a valid cmd - and then have it executed by the cmd ioctl (asyncronously). + and then have it executed by the cmd ioctl (asynchronously). cmdtest returns 1,2,3,4 or 0, depending on which tests the command passes. diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index c89bd6cde8bc..4ad6adfcbb9c 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -83,36 +83,6 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3 #define REG_EED 0x32 #define REG_EEC 0x34 -static const int s526_ports[] = { - REG_TCR, - REG_WDC, - REG_DAC, - REG_ADC, - REG_ADD, - REG_DIO, - REG_IER, - REG_ISR, - REG_MSC, - REG_C0L, - REG_C0H, - REG_C0M, - REG_C0C, - REG_C1L, - REG_C1H, - REG_C1M, - REG_C1C, - REG_C2L, - REG_C2H, - REG_C2M, - REG_C2C, - REG_C3L, - REG_C3H, - REG_C3M, - REG_C3C, - REG_EED, - REG_EEC -}; - struct counter_mode_register_t { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned short coutSource:1; @@ -148,122 +118,48 @@ union cmReg { unsigned short value; }; -#define MAX_GPCT_CONFIG_DATA 6 - -/* Different Application Classes for GPCT Subdevices */ -/* The list is not exhaustive and needs discussion! */ -enum S526_GPCT_APP_CLASS { - CountingAndTimeMeasurement, - SinglePulseGeneration, - PulseTrainGeneration, - PositionMeasurement, - Miscellaneous -}; - -/* Config struct for different GPCT subdevice Application Classes and - their options -*/ -struct s526GPCTConfig { - enum S526_GPCT_APP_CLASS app; - int data[MAX_GPCT_CONFIG_DATA]; -}; - -/* - * Board descriptions for two imaginary boards. Describing the - * boards in this way is optional, and completely driver-dependent. - * Some drivers use arrays such as this, other do not. - */ -struct s526_board { - const char *name; - int gpct_chans; - int gpct_bits; - int ad_chans; - int ad_bits; - int da_chans; - int da_bits; - int have_dio; -}; - -static const struct s526_board s526_boards[] = { - { - .name = "s526", - .gpct_chans = 4, - .gpct_bits = 24, - .ad_chans = 8, - .ad_bits = 16, - .da_chans = 4, - .da_bits = 16, - .have_dio = 1, - } -}; - -#define ADDR_REG(reg) (dev->iobase + (reg)) -#define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8) - -/* this structure is for data unique to this hardware driver. If - several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device - struct. -*/ struct s526_private { unsigned int ao_readback[2]; - struct s526GPCTConfig s526_gpct_config[4]; - unsigned short s526_ai_config; + unsigned int gpct_config[4]; + unsigned short ai_config; }; -/* - * most drivers define the following macro to make it easy to - * access the private structure. - */ -#define devpriv ((struct s526_private *)dev->private) - static int s526_gpct_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - int i; /* counts the Data */ - int counter_channel = CR_CHAN(insn->chanspec); - unsigned short datalow; - unsigned short datahigh; - - /* Check if (n > 0) */ - if (insn->n <= 0) { - printk(KERN_ERR "s526: INSN_READ: n should be > 0\n"); - return -EINVAL; - } - /* Read the low word first */ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned long chan_iobase = dev->iobase + chan * 8; + unsigned int lo; + unsigned int hi; + int i; + for (i = 0; i < insn->n; i++) { - datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel)); - datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel)); - data[i] = (int)(datahigh & 0x00FF); - data[i] = (data[i] << 16) | (datalow & 0xFFFF); - /* printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", - counter_channel, data[i], datahigh, datalow); */ + /* Read the low word first */ + lo = inw(chan_iobase + REG_C0L) & 0xffff; + hi = inw(chan_iobase + REG_C0H) & 0xff; + + data[i] = (hi << 16) | lo; } - return i; + + return insn->n; } static int s526_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ - int i; - short value; + struct s526_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned long chan_iobase = dev->iobase + chan * 8; + unsigned int val; union cmReg cmReg; - /* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", - subdev_channel); */ - - for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) { - devpriv->s526_gpct_config[subdev_channel].data[i] = - insn->data[i]; -/* printk("data[%d]=%x\n", i, insn->data[i]); */ - } - /* Check what type of Counter the user requested, data[0] contains */ /* the Application type */ - switch (insn->data[0]) { + switch (data[0]) { case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: /* data[0]: Application Type @@ -271,9 +167,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[2]: Pre-load Register Value data[3]: Conter Control Register */ - printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring Encoder\n"); - devpriv->s526_gpct_config[subdev_channel].app = - PositionMeasurement; + devpriv->gpct_config[chan] = data[0]; #if 0 /* Example of Counter Application */ @@ -290,34 +184,32 @@ static int s526_gpct_insn_config(struct comedi_device *dev, cmReg.reg.preloadRegSel = 0; /* PR0 */ cmReg.reg.reserved = 0; - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + outw(cmReg.value, chan_iobase + REG_C0M); - outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); - outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + outw(0x0001, chan_iobase + REG_C0H); + outw(0x3C68, chan_iobase + REG_C0L); /* Reset the counter */ - outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x8000, chan_iobase + REG_C0C); /* Load the counter from PR0 */ - outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x4000, chan_iobase + REG_C0C); /* Reset RCAP (fires one-shot) */ - outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x0008, chan_iobase + REG_C0C); #endif #if 1 /* Set Counter Mode Register */ - cmReg.value = insn->data[1] & 0xFFFF; - -/* printk("s526: Counter Mode register=%x\n", cmReg.value); */ - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + cmReg.value = data[1] & 0xffff; + outw(cmReg.value, chan_iobase + REG_C0M); /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x8000, chan_iobase + REG_C0C); /* Load the counter from PR0 - * outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + * outw(0x4000, chan_iobase + REG_C0C); */ } #else @@ -325,47 +217,47 @@ static int s526_gpct_insn_config(struct comedi_device *dev, cmReg.reg.countDirCtrl = 0; /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ - if (insn->data[1] == GPCT_X2) + if (data[1] == GPCT_X2) cmReg.reg.clockSource = 1; - else if (insn->data[1] == GPCT_X4) + else if (data[1] == GPCT_X4) cmReg.reg.clockSource = 2; else cmReg.reg.clockSource = 0; /* When to take into account the indexpulse: */ - /*if (insn->data[2] == GPCT_IndexPhaseLowLow) { - } else if (insn->data[2] == GPCT_IndexPhaseLowHigh) { - } else if (insn->data[2] == GPCT_IndexPhaseHighLow) { - } else if (insn->data[2] == GPCT_IndexPhaseHighHigh) { + /*if (data[2] == GPCT_IndexPhaseLowLow) { + } else if (data[2] == GPCT_IndexPhaseLowHigh) { + } else if (data[2] == GPCT_IndexPhaseHighLow) { + } else if (data[2] == GPCT_IndexPhaseHighHigh) { }*/ /* Take into account the index pulse? */ - if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX) + if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) /* Auto load with INDEX^ */ cmReg.reg.autoLoadResetRcap = 4; /* Set Counter Mode Register */ - cmReg.value = (short)(insn->data[1] & 0xFFFF); - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + cmReg.value = data[1] & 0xffff; + outw(cmReg.value, chan_iobase + REG_C0M); /* Load the pre-load register high word */ - value = (short)((insn->data[2] >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + val = (data[2] >> 16) & 0xffff; + outw(val, chan_iobase + REG_C0H); /* Load the pre-load register low word */ - value = (short)(insn->data[2] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + val = data[2] & 0xffff; + outw(val, chan_iobase + REG_C0L); /* Write the Counter Control Register */ - if (insn->data[3] != 0) { - value = (short)(insn->data[3] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + if (data[3]) { + val = data[3] & 0xffff; + outw(val, chan_iobase + REG_C0C); } /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x8000, chan_iobase + REG_C0C); /* Load the counter from PR0 */ - outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + outw(0x4000, chan_iobase + REG_C0C); } #endif break; @@ -378,40 +270,38 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[3]: Pre-load Register 1 Value data[4]: Conter Control Register */ - printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring SPG\n"); - devpriv->s526_gpct_config[subdev_channel].app = - SinglePulseGeneration; + devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ - cmReg.value = (short)(insn->data[1] & 0xFFFF); + cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + outw(cmReg.value, chan_iobase + REG_C0M); /* Load the pre-load register 0 high word */ - value = (short)((insn->data[2] >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + val = (data[2] >> 16) & 0xffff; + outw(val, chan_iobase + REG_C0H); /* Load the pre-load register 0 low word */ - value = (short)(insn->data[2] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + val = data[2] & 0xffff; + outw(val, chan_iobase + REG_C0L); /* Set Counter Mode Register */ - cmReg.value = (short)(insn->data[1] & 0xFFFF); + cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + outw(cmReg.value, chan_iobase + REG_C0M); /* Load the pre-load register 1 high word */ - value = (short)((insn->data[3] >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + val = (data[3] >> 16) & 0xffff; + outw(val, chan_iobase + REG_C0H); /* Load the pre-load register 1 low word */ - value = (short)(insn->data[3] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + val = data[3] & 0xffff; + outw(val, chan_iobase + REG_C0L); /* Write the Counter Control Register */ - if (insn->data[4] != 0) { - value = (short)(insn->data[4] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + if (data[4]) { + val = data[4] & 0xffff; + outw(val, chan_iobase + REG_C0C); } break; @@ -423,45 +313,42 @@ static int s526_gpct_insn_config(struct comedi_device *dev, data[3]: Pre-load Register 1 Value data[4]: Conter Control Register */ - printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring PTG\n"); - devpriv->s526_gpct_config[subdev_channel].app = - PulseTrainGeneration; + devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ - cmReg.value = (short)(insn->data[1] & 0xFFFF); + cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + outw(cmReg.value, chan_iobase + REG_C0M); /* Load the pre-load register 0 high word */ - value = (short)((insn->data[2] >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + val = (data[2] >> 16) & 0xffff; + outw(val, chan_iobase + REG_C0H); /* Load the pre-load register 0 low word */ - value = (short)(insn->data[2] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + val = data[2] & 0xffff; + outw(val, chan_iobase + REG_C0L); /* Set Counter Mode Register */ - cmReg.value = (short)(insn->data[1] & 0xFFFF); + cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + outw(cmReg.value, chan_iobase + REG_C0M); /* Load the pre-load register 1 high word */ - value = (short)((insn->data[3] >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + val = (data[3] >> 16) & 0xffff; + outw(val, chan_iobase + REG_C0H); /* Load the pre-load register 1 low word */ - value = (short)(insn->data[3] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + val = data[3] & 0xffff; + outw(val, chan_iobase + REG_C0L); /* Write the Counter Control Register */ - if (insn->data[4] != 0) { - value = (short)(insn->data[4] & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + if (data[4]) { + val = data[4] & 0xffff; + outw(val, chan_iobase + REG_C0C); } break; default: - printk(KERN_ERR "s526: unsupported GPCT_insn_config\n"); return -EINVAL; break; } @@ -470,65 +357,40 @@ static int s526_gpct_insn_config(struct comedi_device *dev, } static int s526_gpct_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ - short value; - union cmReg cmReg; - - printk(KERN_INFO "s526: GPCT_INSN_WRITE on channel %d\n", - subdev_channel); - cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel)); - printk(KERN_INFO "s526: Counter Mode Register: %x\n", cmReg.value); - /* Check what Application of Counter this channel is configured for */ - switch (devpriv->s526_gpct_config[subdev_channel].app) { - case PositionMeasurement: - printk(KERN_INFO "S526: INSN_WRITE: PM\n"); - outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, - subdev_channel)); - outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); - break; + struct s526_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned long chan_iobase = dev->iobase + chan * 8; - case SinglePulseGeneration: - printk(KERN_INFO "S526: INSN_WRITE: SPG\n"); - outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, - subdev_channel)); - outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); - break; + inw(chan_iobase + REG_C0M); /* Is this read required? */ - case PulseTrainGeneration: + /* Check what Application of Counter this channel is configured for */ + switch (devpriv->gpct_config[chan]) { + case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: /* data[0] contains the PULSE_WIDTH data[1] contains the PULSE_PERIOD @pre PULSE_PERIOD > PULSE_WIDTH > 0 The above periods must be expressed as a multiple of the pulse frequency on the selected source */ - printk(KERN_INFO "S526: INSN_WRITE: PTG\n"); - if ((insn->data[1] > insn->data[0]) && (insn->data[0] > 0)) { - (devpriv->s526_gpct_config[subdev_channel]).data[0] = - insn->data[0]; - (devpriv->s526_gpct_config[subdev_channel]).data[1] = - insn->data[1]; - } else { - printk(KERN_ERR "s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n", - insn->data[0], insn->data[1]); + if ((data[1] < data[0]) || !data[0]) return -EINVAL; - } - value = (short)((*data >> 16) & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); - value = (short)(*data & 0xFFFF); - outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + /* Fall thru to write the PULSE_WIDTH */ + + case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: + case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: + outw((data[0] >> 16) & 0xffff, chan_iobase + REG_C0H); + outw(data[0] & 0xffff, chan_iobase + REG_C0L); break; - default: /* Impossible */ - printk - ("s526: INSN_WRITE: Functionality %d not implemented yet\n", - devpriv->s526_gpct_config[subdev_channel].app); + + default: return -EINVAL; - break; } - /* return the number of samples written */ + return insn->n; } @@ -537,6 +399,7 @@ static int s526_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct s526_private *devpriv = dev->private; int result = -EINVAL; if (insn->n < 1) @@ -552,62 +415,50 @@ static int s526_ai_insn_config(struct comedi_device *dev, * INSN_READ handler. */ /* Enable ADC interrupt */ - outw(ISR_ADC_DONE, ADDR_REG(REG_IER)); -/* printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC))); */ - devpriv->s526_ai_config = (data[0] & 0x3FF) << 5; + outw(ISR_ADC_DONE, dev->iobase + REG_IER); + devpriv->ai_config = (data[0] & 0x3ff) << 5; if (data[1] > 0) - devpriv->s526_ai_config |= 0x8000; /* set the delay */ + devpriv->ai_config |= 0x8000; /* set the delay */ - devpriv->s526_ai_config |= 0x0001; /* ADC start bit. */ + devpriv->ai_config |= 0x0001; /* ADC start bit */ return result; } -/* - * "instructions" read/write data in "one-shot" or "software-triggered" - * mode. - */ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct s526_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int n, i; - int chan = CR_CHAN(insn->chanspec); unsigned short value; unsigned int d; unsigned int status; /* Set configured delay, enable channel for this channel only, * select "ADC read" channel, set "ADC start" bit. */ - value = (devpriv->s526_ai_config & 0x8000) | - ((1 << 5) << chan) | (chan << 1) | 0x0001; + value = (devpriv->ai_config & 0x8000) | + ((1 << 5) << chan) | (chan << 1) | 0x0001; /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion */ - outw(value, ADDR_REG(REG_ADC)); -/* printk("s526: Wrote 0x%04x to ADC\n", value); */ -/* printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC))); */ + outw(value, dev->iobase + REG_ADC); #define TIMEOUT 100 /* wait for conversion to end */ for (i = 0; i < TIMEOUT; i++) { - status = inw(ADDR_REG(REG_ISR)); + status = inw(dev->iobase + REG_ISR); if (status & ISR_ADC_DONE) { - outw(ISR_ADC_DONE, ADDR_REG(REG_ISR)); + outw(ISR_ADC_DONE, dev->iobase + REG_ISR); break; } } - if (i == TIMEOUT) { - /* printk() should be used instead of printk() - * whenever the code can be called from real-time. */ - printk(KERN_ERR "s526: ADC(0x%04x) timeout\n", - inw(ADDR_REG(REG_ISR))); + if (i == TIMEOUT) return -ETIMEDOUT; - } /* read data */ - d = inw(ADDR_REG(REG_ADD)); -/* printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF)); */ + d = inw(dev->iobase + REG_ADD); /* munge data */ data[n] = d ^ 0x8000; @@ -620,40 +471,30 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - int i; - int chan = CR_CHAN(insn->chanspec); + struct s526_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); unsigned short val; + int i; -/* printk("s526_ao_winsn\n"); */ val = chan << 1; -/* outw(val, dev->iobase + REG_DAC); */ - outw(val, ADDR_REG(REG_DAC)); + outw(val, dev->iobase + REG_DAC); - /* Writing a list of values to an AO channel is probably not - * very useful, but that's how the interface is defined. */ for (i = 0; i < insn->n; i++) { - /* a typical programming sequence */ - /* write the data to preload register - * outw(data[i], dev->iobase + REG_ADD); - */ - /* write the data to preload register */ - outw(data[i], ADDR_REG(REG_ADD)); + outw(data[i], dev->iobase + REG_ADD); devpriv->ao_readback[chan] = data[i]; -/* outw(val + 1, dev->iobase + REG_DAC); starts the D/A conversion. */ - outw(val + 1, ADDR_REG(REG_DAC)); /*starts the D/A conversion.*/ + /* starts the D/A conversion */ + outw(val + 1, dev->iobase + REG_DAC); } - /* return the number of samples read/written */ return i; } -/* AO subdevices should have a read insn as well as a write insn. - * Usually this means copying a value stored in devpriv. */ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct s526_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int i; - int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; @@ -661,30 +502,18 @@ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } -/* DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write */ static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ if (data[0]) { s->state &= ~data[0]; s->state |= data[0] & data[1]; - /* Write out the new digital output lines */ - outw(s->state, ADDR_REG(REG_DIO)); + + outw(s->state, dev->iobase + REG_DIO); } - /* on return, data[1] contains the value of the digital - * input and output lines. */ - data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */ - /* or we could just return the software copy of the output values if - * it was a purely digital output subdevice */ - /* data[1]=s->state & 0xFF; */ + data[1] = inw(dev->iobase + REG_DIO) & 0xff; return insn->n; } @@ -693,16 +522,9 @@ static int s526_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); int group, mask; - printk(KERN_INFO "S526 DIO insn_config\n"); - - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ - group = chan >> 2; mask = 0xF << (group << 2); switch (data[0]) { @@ -721,48 +543,31 @@ static int s526_dio_insn_config(struct comedi_device *dev, default: return -EINVAL; } - outw(s->state, ADDR_REG(REG_DIO)); + outw(s->state, dev->iobase + REG_DIO); return 1; } static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct s526_board *board = comedi_board(dev); + struct s526_private *devpriv; struct comedi_subdevice *s; int iobase; - int i, n; int ret; -/* short value; */ -/* int subdev_channel = 0; */ - union cmReg cmReg; - printk(KERN_INFO "comedi%d: s526: ", dev->minor); + dev->board_name = dev->driver->driver_name; iobase = it->options[0]; - if (!iobase || !request_region(iobase, S526_IOSIZE, board->name)) { + if (!iobase || !request_region(iobase, S526_IOSIZE, dev->board_name)) { comedi_error(dev, "I/O port conflict"); return -EIO; } dev->iobase = iobase; - printk("iobase=0x%lx\n", dev->iobase); - - /*** make it a little quieter, exw, 8/29/06 - for (i = 0; i < S526_NUM_PORTS; i++) { - printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]), - inw(ADDR_REG(s526_ports[i]))); - } - ***/ - - dev->board_name = board->name; - -/* - * Allocate the private structure area. alloc_private() is a - * convenient macro defined in comedidev.h. - */ - if (alloc_private(dev, sizeof(struct s526_private)) < 0) - return -ENOMEM; + ret = alloc_private(dev, sizeof(*devpriv)); + if (ret) + return ret; + devpriv = dev->private; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -772,33 +577,22 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */ s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; - /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */ - s->n_chan = board->gpct_chans; + s->n_chan = 4; s->maxdata = 0x00ffffff; /* 24 bit counter */ s->insn_read = s526_gpct_rinsn; s->insn_config = s526_gpct_insn_config; s->insn_write = s526_gpct_winsn; - /* Command are not implemented yet, however they are necessary to - allocate the necessary memory for the comedi_async struct (used - to trigger the GPCT in case of pulsegenerator function */ - /* s->do_cmd = s526_gpct_cmd; */ - /* s->do_cmdtest = s526_gpct_cmdtest; */ - /* s->cancel = s526_gpct_cancel; */ - s = &dev->subdevices[1]; - /* dev->read_subdev=s; */ /* analog input subdevice */ s->type = COMEDI_SUBD_AI; - /* we support differential */ s->subdev_flags = SDF_READABLE | SDF_DIFF; /* channels 0 to 7 are the regular differential inputs */ /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */ s->n_chan = 10; s->maxdata = 0xffff; s->range_table = &range_bipolar10; - s->len_chanlist = 16; /* This is the maximum chanlist length that - the board can handle */ + s->len_chanlist = 16; s->insn_read = s526_ai_rinsn; s->insn_config = s526_ai_insn_config; @@ -814,103 +608,16 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[3]; /* digital i/o subdevice */ - if (board->have_dio) { - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = s526_dio_insn_bits; - s->insn_config = s526_dio_insn_config; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - printk(KERN_INFO "attached\n"); - - return 1; - -#if 0 - /* Example of Counter Application */ - /* One-shot (software trigger) */ - cmReg.reg.coutSource = 0; /* out RCAP */ - cmReg.reg.coutPolarity = 1; /* Polarity inverted */ - cmReg.reg.autoLoadResetRcap = 1;/* Auto load 0:disabled, 1:enabled */ - cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */ - cmReg.reg.ctEnableCtrl = 2; /* Hardware */ - cmReg.reg.clockSource = 2; /* Internal */ - cmReg.reg.countDir = 1; /* Down */ - cmReg.reg.countDirCtrl = 1; /* Software */ - cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */ - cmReg.reg.preloadRegSel = 0; /* PR0 */ - cmReg.reg.reserved = 0; - - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); - - outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); - outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); - - /* Reset the counter */ - outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); - /* Load the counter from PR0 */ - outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); - /* Reset RCAP (fires one-shot) */ - outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); - -#else - - /* Set Counter Mode Register */ - cmReg.reg.coutSource = 0; /* out RCAP */ - cmReg.reg.coutPolarity = 0; /* Polarity inverted */ - cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */ - cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */ - cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */ - cmReg.reg.clockSource = 3; /* x4 */ - cmReg.reg.countDir = 0; /* up */ - cmReg.reg.countDirCtrl = 0; /* quadrature */ - cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */ - cmReg.reg.preloadRegSel = 0; /* PR0 */ - cmReg.reg.reserved = 0; - - n = 0; - printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n", - cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); - udelay(1000); - printk(KERN_INFO "Read back mode reg=0x%04x\n", - inw(ADDR_CHAN_REG(REG_C0M, n))); - - /* Load the pre-load register high word */ -/* value = (short) (0x55); */ -/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */ - - /* Load the pre-load register low word */ -/* value = (short)(0xaa55); */ -/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */ - - /* Write the Counter Control Register */ -/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */ - - /* Reset the counter if it is software preload */ - if (cmReg.reg.autoLoadResetRcap == 0) { - /* Reset the counter */ - outw(0x8000, ADDR_CHAN_REG(REG_C0C, n)); - /* Load the counter from PR0 */ - outw(0x4000, ADDR_CHAN_REG(REG_C0C, n)); - } + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = s526_dio_insn_bits; + s->insn_config = s526_dio_insn_config; - outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); - udelay(1000); - printk(KERN_INFO "Read back mode reg=0x%04x\n", - inw(ADDR_CHAN_REG(REG_C0M, n))); + dev_info(dev->class_dev, "%s attached\n", dev->board_name); -#endif - printk(KERN_INFO "Current registres:\n"); - - for (i = 0; i < S526_NUM_PORTS; i++) { - printk(KERN_INFO "0x%02lx: 0x%04x\n", - ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i]))); - } return 1; } @@ -925,9 +632,6 @@ static struct comedi_driver s526_driver = { .module = THIS_MODULE, .attach = s526_attach, .detach = s526_detach, - .board_name = &s526_boards[0].name, - .offset = sizeof(struct s526_board), - .num_names = ARRAY_SIZE(s526_boards), }; module_comedi_driver(s526_driver); diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 7aac213fb6ab..bc5fc5cc4641 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2293,10 +2293,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) usbduxsub_tmp->pwm_cmd_running = 0; } -/* common part of attach and attach_usb */ static int usbdux_attach_common(struct comedi_device *dev, - struct usbduxsub *udev, - void *aux_data, int aux_len) + struct usbduxsub *udev) { int ret; struct comedi_subdevice *s = NULL; @@ -2306,10 +2304,6 @@ static int usbdux_attach_common(struct comedi_device *dev, /* pointer back to the corresponding comedi device */ udev->comedidev = dev; - /* trying to upload the firmware into the chip */ - if (aux_data) - firmwareUpload(udev, aux_data, aux_len); - dev->board_name = "usbdux"; /* set number of subdevices */ @@ -2429,48 +2423,6 @@ static int usbdux_attach_common(struct comedi_device *dev, return 0; } -/* is called when comedi-config is called */ -static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ - int ret; - int index; - int i; - void *aux_data; - int aux_len; - - dev->private = NULL; - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - if (aux_data == NULL) - aux_len = 0; - else if (aux_len == 0) - aux_data = NULL; - - down(&start_stop_sem); - /* find a valid device which has been detected by the probe function of - * the usb */ - index = -1; - for (i = 0; i < NUMUSBDUX; i++) { - if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { - index = i; - break; - } - } - - if (index < 0) { - printk(KERN_ERR - "comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n", - dev->minor); - ret = -ENODEV; - } else - ret = usbdux_attach_common(dev, &usbduxsub[index], - aux_data, aux_len); - up(&start_stop_sem); - return ret; -} - -/* is called from comedi_usb_auto_config() */ static int usbdux_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -2492,7 +2444,7 @@ static int usbdux_attach_usb(struct comedi_device *dev, dev->minor); ret = -ENODEV; } else - ret = usbdux_attach_common(dev, this_usbduxsub, NULL, 0); + ret = usbdux_attach_common(dev, this_usbduxsub); up(&start_stop_sem); return ret; } @@ -2513,9 +2465,8 @@ static void usbdux_detach(struct comedi_device *dev) static struct comedi_driver usbdux_driver = { .driver_name = "usbdux", .module = THIS_MODULE, - .attach = usbdux_attach, - .detach = usbdux_detach, .attach_usb = usbdux_attach_usb, + .detach = usbdux_detach, }; static void usbdux_firmware_request_complete_handler(const struct firmware *fw, diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 3f68fc396301..0f6c1392f6ce 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1430,10 +1430,8 @@ static void tidy_up(struct usbduxfastsub_s *udfs) udfs->ai_cmd_running = 0; } -/* common part of attach and attach_usb */ static int usbduxfast_attach_common(struct comedi_device *dev, - struct usbduxfastsub_s *udfs, - void *aux_data, int aux_len) + struct usbduxfastsub_s *udfs) { int ret; struct comedi_subdevice *s; @@ -1441,9 +1439,6 @@ static int usbduxfast_attach_common(struct comedi_device *dev, down(&udfs->sem); /* pointer back to the corresponding comedi device */ udfs->comedidev = dev; - /* trying to upload the firmware into the chip */ - if (aux_data) - firmwareUpload(udfs, aux_data, aux_len); dev->board_name = "usbduxfast"; ret = comedi_alloc_subdevices(dev, 1); if (ret) { @@ -1485,48 +1480,6 @@ static int usbduxfast_attach_common(struct comedi_device *dev, return 0; } -/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ -static int usbduxfast_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - int ret; - int index; - int i; - void *aux_data; - int aux_len; - - dev->private = NULL; - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - if (aux_data == NULL) - aux_len = 0; - else if (aux_len == 0) - aux_data = NULL; - down(&start_stop_sem); - /* - * find a valid device which has been detected by the - * probe function of the usb - */ - index = -1; - for (i = 0; i < NUMUSBDUXFAST; i++) { - if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { - index = i; - break; - } - } - if (index < 0) { - dev_err(dev->class_dev, - "usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n"); - ret = -ENODEV; - } else - ret = usbduxfast_attach_common(dev, &usbduxfastsub[index], - aux_data, aux_len); - up(&start_stop_sem); - return ret; -} - -/* is called from comedi_usb_auto_config() */ static int usbduxfast_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -1545,7 +1498,7 @@ static int usbduxfast_attach_usb(struct comedi_device *dev, "usbduxfast: error: attach_usb failed, already attached\n"); ret = -ENODEV; } else - ret = usbduxfast_attach_common(dev, udfs, NULL, 0); + ret = usbduxfast_attach_common(dev, udfs); up(&start_stop_sem); return ret; } @@ -1568,9 +1521,8 @@ static void usbduxfast_detach(struct comedi_device *dev) static struct comedi_driver usbduxfast_driver = { .driver_name = "usbduxfast", .module = THIS_MODULE, - .attach = usbduxfast_attach, - .detach = usbduxfast_detach, .attach_usb = usbduxfast_attach_usb, + .detach = usbduxfast_detach, }; static void usbduxfast_firmware_request_complete_handler(const struct firmware diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 034f5dfc05f8..b4ab83f1215f 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2301,10 +2301,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) usbduxsub_tmp->pwm_cmd_running = 0; } -/* common part of attach and attach_usb */ static int usbduxsigma_attach_common(struct comedi_device *dev, - struct usbduxsub *uds, - void *aux_data, int aux_len) + struct usbduxsub *uds) { int ret; struct comedi_subdevice *s; @@ -2314,9 +2312,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, down(&uds->sem); /* pointer back to the corresponding comedi device */ uds->comedidev = dev; - /* trying to upload the firmware into the FX2 */ - if (aux_data) - firmwareUpload(uds, aux_data, aux_len); dev->board_name = "usbduxsigma"; /* set number of subdevices */ if (uds->high_speed) @@ -2419,47 +2414,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, return 0; } -/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */ -static int usbduxsigma_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - int ret; - int index; - int i; - void *aux_data; - int aux_len; - - dev->private = NULL; - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - if (aux_data == NULL) - aux_len = 0; - else if (aux_len == 0) - aux_data = NULL; - - down(&start_stop_sem); - /* find a valid device which has been detected by the probe function of - * the usb */ - index = -1; - for (i = 0; i < NUMUSBDUX; i++) { - if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { - index = i; - break; - } - } - if (index < 0) { - dev_err(dev->class_dev, - "usbduxsigma: error: attach failed, dev not connected to the usb bus.\n"); - ret = -ENODEV; - } else - ret = usbduxsigma_attach_common(dev, &usbduxsub[index], - aux_data, aux_len); - up(&start_stop_sem); - return ret; -} - -/* is called from comedi_usb_auto_config() */ static int usbduxsigma_attach_usb(struct comedi_device *dev, struct usb_interface *uinterf) { @@ -2478,7 +2432,7 @@ static int usbduxsigma_attach_usb(struct comedi_device *dev, "usbduxsigma: error: attach_usb failed, already attached\n"); ret = -ENODEV; } else - ret = usbduxsigma_attach_common(dev, uds, NULL, 0); + ret = usbduxsigma_attach_common(dev, uds); up(&start_stop_sem); return ret; } @@ -2499,9 +2453,8 @@ static void usbduxsigma_detach(struct comedi_device *dev) static struct comedi_driver usbduxsigma_driver = { .driver_name = "usbduxsigma", .module = THIS_MODULE, - .attach = usbduxsigma_attach, - .detach = usbduxsigma_detach, .attach_usb = usbduxsigma_attach_usb, + .detach = usbduxsigma_detach, }; static void usbdux_firmware_request_complete_handler(const struct firmware *fw, diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index f96416d1d2f7..3f20ea55b8d0 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -80,7 +80,9 @@ int comedi_close(struct comedi_device *d) } EXPORT_SYMBOL(comedi_close); -static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) +static int comedi_do_insn(struct comedi_device *dev, + struct comedi_insn *insn, + unsigned int *data) { struct comedi_subdevice *s; int ret = 0; @@ -115,11 +117,11 @@ static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn) switch (insn->insn) { case INSN_BITS: - ret = s->insn_bits(dev, s, insn, insn->data); + ret = s->insn_bits(dev, s, insn, data); break; case INSN_CONFIG: /* XXX should check instruction length */ - ret = s->insn_config(dev, s, insn, insn->data); + ret = s->insn_config(dev, s, insn, data); break; default: ret = -EINVAL; @@ -140,11 +142,10 @@ int comedi_dio_config(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_CONFIG; insn.n = 1; - insn.data = &io; insn.subdev = subdev; insn.chanspec = CR_PACK(chan, 0, 0); - return comedi_do_insn(dev, &insn); + return comedi_do_insn(dev, &insn, &io); } EXPORT_SYMBOL(comedi_dio_config); @@ -158,13 +159,12 @@ int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev, memset(&insn, 0, sizeof(insn)); insn.insn = INSN_BITS; insn.n = 2; - insn.data = data; insn.subdev = subdev; data[0] = mask; data[1] = *bits; - ret = comedi_do_insn(dev, &insn); + ret = comedi_do_insn(dev, &insn, data); *bits = data[1]; diff --git a/drivers/staging/csr/sme_blocking.c b/drivers/staging/csr/sme_blocking.c index acf0f0fe3b37..543e8f2c407a 100644 --- a/drivers/staging/csr/sme_blocking.c +++ b/drivers/staging/csr/sme_blocking.c @@ -18,10 +18,10 @@ /* - * This file also contains the implementation of the asyncronous + * This file also contains the implementation of the asynchronous * requests to the SME. * - * Before calling an asyncronous SME function, we call sme_init_request() + * Before calling an asynchronous SME function, we call sme_init_request() * which gets hold of the SME semaphore and updates the request status. * The semaphore makes sure that there is only one pending request to * the SME at a time. diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig new file mode 100644 index 000000000000..14b4449df234 --- /dev/null +++ b/drivers/staging/imx-drm/Kconfig @@ -0,0 +1,35 @@ +config DRM_IMX + tristate "DRM Support for Freescale i.MX" + select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER + select DRM_KMS_CMA_HELPER + depends on DRM && ARCH_MXC + help + enable i.MX graphics support + +config DRM_IMX_FB_HELPER + tristate "provide legacy framebuffer /dev/fb0" + select DRM_KMS_CMA_HELPER + depends on DRM_IMX + help + The DRM framework can provide a legacy /dev/fb0 framebuffer + for your device. This is necessary to get a framebuffer console + and also for appplications using the legacy framebuffer API + +config DRM_IMX_PARALLEL_DISPLAY + tristate "Support for parallel displays" + depends on DRM_IMX + +config DRM_IMX_IPUV3_CORE + tristate "IPUv3 core support" + depends on DRM_IMX + help + Choose this if you have a i.MX5/6 system and want + to use the IPU. This option only enables IPU base + support. + +config DRM_IMX_IPUV3 + tristate "DRM Support for i.MX IPUv3" + depends on DRM_IMX + help + Choose this if you have a i.MX5 or i.MX6 processor. diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile new file mode 100644 index 000000000000..83a9056546e6 --- /dev/null +++ b/drivers/staging/imx-drm/Makefile @@ -0,0 +1,9 @@ + +imxdrm-objs := imx-drm-core.o imx-fb.o + +obj-$(CONFIG_DRM_IMX) += imxdrm.o + +obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o +obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o +obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/ +obj-$(CONFIG_DRM_IMX_IPUV3) += ipuv3-crtc.o diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO new file mode 100644 index 000000000000..e52adc44e607 --- /dev/null +++ b/drivers/staging/imx-drm/TODO @@ -0,0 +1,22 @@ +TODO: +- get DRM Maintainer review for this code +- Factor out more code to common helper functions +- decide where to put the base driver. It is not specific to a subsystem + and would be used by DRM/KMS and media/V4L2 +- convert irq driver to irq_domain_add_linear + +Missing features (not necessarily for moving out of staging): + +- Add KMS plane support for CRTC driver +- Add LDB (LVDS Display Bridge) support +- Add i.MX6 HDMI support +- Add support for IC (Image converter) +- Add support for CSI (CMOS Sensor interface) +- Add support for VDIC (Video Deinterlacer) + +Many work-in-progress patches for the above features exist. Contact +Sascha Hauer <[email protected]> if you are interested in working +on a specific feature. + +Please send any patches to Greg Kroah-Hartman <[email protected]> and +Sascha Hauer <[email protected]> diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c new file mode 100644 index 000000000000..1913199ba16e --- /dev/null +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -0,0 +1,884 @@ +/* + * Freescale i.MX drm driver + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that 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. + * + */ + +#include <linux/device.h> +#include <linux/platform_device.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> +#include <linux/fb.h> +#include <linux/module.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "imx-drm.h" + +#define MAX_CRTC 4 + +struct crtc_cookie { + void *cookie; + int id; + struct list_head list; +}; + +struct imx_drm_device { + struct drm_device *drm; + struct device *dev; + struct list_head crtc_list; + struct list_head encoder_list; + struct list_head connector_list; + struct mutex mutex; + int references; + int pipes; + struct drm_fbdev_cma *fbhelper; +}; + +struct imx_drm_crtc { + struct drm_crtc *crtc; + struct list_head list; + struct imx_drm_device *imxdrm; + int pipe; + struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; + struct module *owner; + struct crtc_cookie cookie; +}; + +struct imx_drm_encoder { + struct drm_encoder *encoder; + struct list_head list; + struct module *owner; + struct list_head possible_crtcs; +}; + +struct imx_drm_connector { + struct drm_connector *connector; + struct list_head list; + struct module *owner; +}; + +static int imx_drm_driver_firstopen(struct drm_device *drm) +{ + if (!imx_drm_device_get()) + return -EINVAL; + + return 0; +} + +static void imx_drm_driver_lastclose(struct drm_device *drm) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + + if (imxdrm->fbhelper) + drm_fbdev_cma_restore_mode(imxdrm->fbhelper); + + imx_drm_device_put(); +} + +static int imx_drm_driver_unload(struct drm_device *drm) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + + drm_mode_config_cleanup(imxdrm->drm); + drm_kms_helper_poll_fini(imxdrm->drm); + + return 0; +} + +/* + * We don't care at all for crtc numbers, but the core expects the + * crtcs to be numbered + */ +static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm, + int num) +{ + struct imx_drm_crtc *imx_drm_crtc; + + list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) + if (imx_drm_crtc->pipe == num) + return imx_drm_crtc; + return NULL; +} + +int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, + u32 interface_pix_fmt) +{ + struct imx_drm_device *imxdrm = crtc->dev->dev_private; + struct imx_drm_crtc *imx_crtc; + struct imx_drm_crtc_helper_funcs *helper; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) + if (imx_crtc->crtc == crtc) + goto found; + + mutex_unlock(&imxdrm->mutex); + + return -EINVAL; +found: + mutex_unlock(&imxdrm->mutex); + + helper = &imx_crtc->imx_drm_helper_funcs; + if (helper->set_interface_pix_fmt) + return helper->set_interface_pix_fmt(crtc, + encoder_type, interface_pix_fmt); + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format); + +int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) +{ + return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); + +void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) +{ + drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); + +void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) +{ + drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); + +static int imx_drm_enable_vblank(struct drm_device *drm, int crtc) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + struct imx_drm_crtc *imx_drm_crtc; + int ret; + + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); + if (!imx_drm_crtc) + return -EINVAL; + + if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) + return -ENOSYS; + + ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank( + imx_drm_crtc->crtc); + + return ret; +} + +static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + struct imx_drm_crtc *imx_drm_crtc; + + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); + if (!imx_drm_crtc) + return; + + if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) + return; + + imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); +} + +static const struct file_operations imx_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = drm_gem_cma_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, + .llseek = noop_llseek, +}; + +static struct imx_drm_device *imx_drm_device; + +static struct imx_drm_device *__imx_drm_device(void) +{ + return imx_drm_device; +} + +struct drm_device *imx_drm_device_get(void) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *enc; + struct imx_drm_connector *con; + struct imx_drm_crtc *crtc; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(enc, &imxdrm->encoder_list, list) { + if (!try_module_get(enc->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(enc->owner)); + goto unwind_enc; + } + } + + list_for_each_entry(con, &imxdrm->connector_list, list) { + if (!try_module_get(con->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(con->owner)); + goto unwind_con; + } + } + + list_for_each_entry(crtc, &imxdrm->crtc_list, list) { + if (!try_module_get(crtc->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(crtc->owner)); + goto unwind_crtc; + } + } + + imxdrm->references++; + + mutex_unlock(&imxdrm->mutex); + + return imxdrm->drm; + +unwind_crtc: + list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list) + module_put(crtc->owner); +unwind_con: + list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list) + module_put(con->owner); +unwind_enc: + list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list) + module_put(enc->owner); + + mutex_unlock(&imxdrm->mutex); + + return NULL; + +} +EXPORT_SYMBOL_GPL(imx_drm_device_get); + +void imx_drm_device_put(void) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *enc; + struct imx_drm_connector *con; + struct imx_drm_crtc *crtc; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(crtc, &imxdrm->crtc_list, list) + module_put(crtc->owner); + + list_for_each_entry(con, &imxdrm->connector_list, list) + module_put(con->owner); + + list_for_each_entry(enc, &imxdrm->encoder_list, list) + module_put(enc->owner); + + imxdrm->references--; + + mutex_unlock(&imxdrm->mutex); +} +EXPORT_SYMBOL_GPL(imx_drm_device_put); + +static int drm_mode_group_reinit(struct drm_device *dev) +{ + struct drm_mode_group *group = &dev->primary->mode_group; + uint32_t *id_list = group->id_list; + int ret; + + ret = drm_mode_group_init_legacy_group(dev, group); + if (ret < 0) + return ret; + + kfree(id_list); + return 0; +} + +/* + * register an encoder to the drm core + */ +static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs); + + drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder, + imx_drm_encoder->encoder->funcs, + imx_drm_encoder->encoder->encoder_type); + + drm_mode_group_reinit(imxdrm->drm); + + return 0; +} + +/* + * unregister an encoder from the drm core + */ +static void imx_drm_encoder_unregister(struct imx_drm_encoder + *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_encoder_cleanup(imx_drm_encoder->encoder); + + drm_mode_group_reinit(imxdrm->drm); +} + +/* + * register a connector to the drm core + */ +static int imx_drm_connector_register( + struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_connector_init(imxdrm->drm, imx_drm_connector->connector, + imx_drm_connector->connector->funcs, + imx_drm_connector->connector->connector_type); + drm_mode_group_reinit(imxdrm->drm); + + return drm_sysfs_connector_add(imx_drm_connector->connector); +} + +/* + * unregister a connector from the drm core + */ +static void imx_drm_connector_unregister( + struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_sysfs_connector_remove(imx_drm_connector->connector); + drm_connector_cleanup(imx_drm_connector->connector); + + drm_mode_group_reinit(imxdrm->drm); +} + +/* + * register a crtc to the drm core + */ +static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + int ret; + + drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, + imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); + ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); + if (ret) + return ret; + + drm_crtc_helper_add(imx_drm_crtc->crtc, + imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); + + drm_mode_group_reinit(imxdrm->drm); + + return 0; +} + +/* + * Called by the CRTC driver when all CRTCs are registered. This + * puts all the pieces together and initializes the driver. + * Once this is called no more CRTCs can be registered since + * the drm core has hardcoded the number of crtcs in several + * places. + */ +static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + int ret; + + imxdrm->drm = drm; + + drm->dev_private = imxdrm; + + /* + * enable drm irq mode. + * - with irq_enabled = 1, we can use the vblank feature. + * + * P.S. note that we wouldn't use drm irq handler but + * just specific driver own one instead because + * drm framework supports only one irq handler and + * drivers can well take care of their interrupts + */ + drm->irq_enabled = 1; + + drm_mode_config_init(drm); + imx_drm_mode_config_init(drm); + + mutex_lock(&imxdrm->mutex); + + drm_kms_helper_poll_init(imxdrm->drm); + + /* setup the grouping for the legacy output */ + ret = drm_mode_group_init_legacy_group(imxdrm->drm, + &imxdrm->drm->primary->mode_group); + if (ret) + goto err_init; + + ret = drm_vblank_init(imxdrm->drm, MAX_CRTC); + if (ret) + goto err_init; + + /* + * with vblank_disable_allowed = 1, vblank interrupt will be disabled + * by drm timer once a current process gives up ownership of + * vblank event.(after drm_vblank_put function is called) + */ + imxdrm->drm->vblank_disable_allowed = 1; + + ret = 0; + +err_init: + mutex_unlock(&imxdrm->mutex); + + return ret; +} + +static void imx_drm_update_possible_crtcs(void) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_crtc *imx_drm_crtc; + struct imx_drm_encoder *enc; + struct crtc_cookie *cookie; + + list_for_each_entry(enc, &imxdrm->encoder_list, list) { + u32 possible_crtcs = 0; + + list_for_each_entry(cookie, &enc->possible_crtcs, list) { + list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) { + if (imx_drm_crtc->cookie.cookie == cookie->cookie && + imx_drm_crtc->cookie.id == cookie->id) { + possible_crtcs |= 1 << imx_drm_crtc->pipe; + } + } + } + enc->encoder->possible_crtcs = possible_crtcs; + enc->encoder->possible_clones = possible_crtcs; + } +} + +/* + * imx_drm_add_crtc - add a new crtc + * + * The return value if !NULL is a cookie for the caller to pass to + * imx_drm_remove_crtc later. + */ +int imx_drm_add_crtc(struct drm_crtc *crtc, + struct imx_drm_crtc **new_crtc, + const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, + struct module *owner, void *cookie, int id) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_crtc *imx_drm_crtc; + const struct drm_crtc_funcs *crtc_funcs; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); + if (!imx_drm_crtc) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; + imx_drm_crtc->pipe = imxdrm->pipes++; + imx_drm_crtc->cookie.cookie = cookie; + imx_drm_crtc->cookie.id = id; + + crtc_funcs = imx_drm_helper_funcs->crtc_funcs; + + imx_drm_crtc->crtc = crtc; + imx_drm_crtc->imxdrm = imxdrm; + + imx_drm_crtc->owner = owner; + + list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list); + + *new_crtc = imx_drm_crtc; + + ret = imx_drm_crtc_register(imx_drm_crtc); + if (ret) + goto err_register; + + imx_drm_update_possible_crtcs(); + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_crtc); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_crtc); + +/* + * imx_drm_remove_crtc - remove a crtc + */ +int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) +{ + struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm; + + mutex_lock(&imxdrm->mutex); + + drm_crtc_cleanup(imx_drm_crtc->crtc); + + list_del(&imx_drm_crtc->list); + + drm_mode_group_reinit(imxdrm->drm); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_crtc); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); + +/* + * imx_drm_add_encoder - add a new encoder + */ +int imx_drm_add_encoder(struct drm_encoder *encoder, + struct imx_drm_encoder **newenc, struct module *owner) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *imx_drm_encoder; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL); + if (!imx_drm_encoder) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_encoder->encoder = encoder; + imx_drm_encoder->owner = owner; + + ret = imx_drm_encoder_register(imx_drm_encoder); + if (ret) { + kfree(imx_drm_encoder); + ret = -ENOMEM; + goto err_register; + } + + list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list); + + *newenc = imx_drm_encoder; + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_encoder); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_encoder); + +int imx_drm_encoder_add_possible_crtcs( + struct imx_drm_encoder *imx_drm_encoder, + struct device_node *np) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct of_phandle_args args; + struct crtc_cookie *c; + int ret = 0; + int i; + + if (!list_empty(&imx_drm_encoder->possible_crtcs)) + return -EBUSY; + + for (i = 0; !ret; i++) { + ret = of_parse_phandle_with_args(np, "crtcs", + "#crtc-cells", i, &args); + if (ret < 0) + break; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + of_node_put(args.np); + return -ENOMEM; + } + + c->cookie = args.np; + c->id = args.args_count > 0 ? args.args[0] : 0; + + of_node_put(args.np); + + mutex_lock(&imxdrm->mutex); + + list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs); + + mutex_unlock(&imxdrm->mutex); + } + + imx_drm_update_possible_crtcs(); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs); + +int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder, + struct drm_crtc *crtc) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_crtc *imx_crtc; + int i = 0; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) { + if (imx_crtc->crtc == crtc) + goto found; + i++; + } + + mutex_unlock(&imxdrm->mutex); + + return -EINVAL; +found: + mutex_unlock(&imxdrm->mutex); + + return i; +} + +/* + * imx_drm_remove_encoder - remove an encoder + */ +int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct crtc_cookie *c, *tmp; + + mutex_lock(&imxdrm->mutex); + + imx_drm_encoder_unregister(imx_drm_encoder); + + list_del(&imx_drm_encoder->list); + + list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs, + list) + kfree(c); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_encoder); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_encoder); + +/* + * imx_drm_add_connector - add a connector + */ +int imx_drm_add_connector(struct drm_connector *connector, + struct imx_drm_connector **new_con, + struct module *owner) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_connector *imx_drm_connector; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL); + if (!imx_drm_connector) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_connector->connector = connector; + imx_drm_connector->owner = owner; + + ret = imx_drm_connector_register(imx_drm_connector); + if (ret) + goto err_register; + + list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list); + + *new_con = imx_drm_connector; + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_connector); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_connector); + +void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + imxdrm->fbhelper = fbdev_helper; +} +EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set); + +/* + * imx_drm_remove_connector - remove a connector + */ +int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + mutex_lock(&imxdrm->mutex); + + imx_drm_connector_unregister(imx_drm_connector); + + list_del(&imx_drm_connector->list); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_connector); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_connector); + +static struct drm_ioctl_desc imx_drm_ioctls[] = { + /* none so far */ +}; + +static struct drm_driver imx_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM, + .load = imx_drm_driver_load, + .unload = imx_drm_driver_unload, + .firstopen = imx_drm_driver_firstopen, + .lastclose = imx_drm_driver_lastclose, + .gem_free_object = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = drm_gem_cma_dumb_create, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .dumb_destroy = drm_gem_cma_dumb_destroy, + + .get_vblank_counter = drm_vblank_count, + .enable_vblank = imx_drm_enable_vblank, + .disable_vblank = imx_drm_disable_vblank, + .ioctls = imx_drm_ioctls, + .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), + .fops = &imx_drm_driver_fops, + .name = "imx-drm", + .desc = "i.MX DRM graphics", + .date = "20120507", + .major = 1, + .minor = 0, + .patchlevel = 0, +}; + +static int imx_drm_platform_probe(struct platform_device *pdev) +{ + imx_drm_device->dev = &pdev->dev; + + return drm_platform_init(&imx_drm_driver, pdev); +} + +static int imx_drm_platform_remove(struct platform_device *pdev) +{ + drm_platform_exit(&imx_drm_driver, pdev); + + return 0; +} + +static struct platform_driver imx_drm_pdrv = { + .probe = imx_drm_platform_probe, + .remove = __devexit_p(imx_drm_platform_remove), + .driver = { + .owner = THIS_MODULE, + .name = "imx-drm", + }, +}; + +static struct platform_device *imx_drm_pdev; + +static int __init imx_drm_init(void) +{ + int ret; + + imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL); + if (!imx_drm_device) + return -ENOMEM; + + mutex_init(&imx_drm_device->mutex); + INIT_LIST_HEAD(&imx_drm_device->crtc_list); + INIT_LIST_HEAD(&imx_drm_device->connector_list); + INIT_LIST_HEAD(&imx_drm_device->encoder_list); + + imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0); + if (!imx_drm_pdev) { + ret = -EINVAL; + goto err_pdev; + } + + imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32), + + ret = platform_driver_register(&imx_drm_pdrv); + if (ret) + goto err_pdrv; + + return 0; + +err_pdrv: + platform_device_unregister(imx_drm_pdev); +err_pdev: + kfree(imx_drm_device); + + return ret; +} + +static void __exit imx_drm_exit(void) +{ + platform_device_unregister(imx_drm_pdev); + platform_driver_unregister(&imx_drm_pdrv); + + kfree(imx_drm_device); +} + +module_init(imx_drm_init); +module_exit(imx_drm_exit); + +MODULE_AUTHOR("Sascha Hauer <[email protected]>"); +MODULE_DESCRIPTION("i.MX drm driver core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h new file mode 100644 index 000000000000..ae28a490c445 --- /dev/null +++ b/drivers/staging/imx-drm/imx-drm.h @@ -0,0 +1,58 @@ +#ifndef _IMX_DRM_H_ +#define _IMX_DRM_H_ + +struct imx_drm_crtc; +struct drm_fbdev_cma; + +struct imx_drm_crtc_helper_funcs { + int (*enable_vblank)(struct drm_crtc *crtc); + void (*disable_vblank)(struct drm_crtc *crtc); + int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type, + u32 pix_fmt); + const struct drm_crtc_helper_funcs *crtc_helper_funcs; + const struct drm_crtc_funcs *crtc_funcs; +}; + +int imx_drm_add_crtc(struct drm_crtc *crtc, + struct imx_drm_crtc **new_crtc, + const struct imx_drm_crtc_helper_funcs *imx_helper_funcs, + struct module *owner, void *cookie, int id); +int imx_drm_remove_crtc(struct imx_drm_crtc *); +int imx_drm_init_drm(struct platform_device *pdev, + int preferred_bpp); +int imx_drm_exit_drm(void); + +int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc); +void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc); +void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc); + +struct imx_drm_encoder; +int imx_drm_add_encoder(struct drm_encoder *encoder, + struct imx_drm_encoder **new_enc, + struct module *owner); +int imx_drm_remove_encoder(struct imx_drm_encoder *); + +struct imx_drm_connector; +int imx_drm_add_connector(struct drm_connector *connector, + struct imx_drm_connector **new_con, + struct module *owner); +int imx_drm_remove_connector(struct imx_drm_connector *); + +void imx_drm_mode_config_init(struct drm_device *drm); + +struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); + +struct drm_device *imx_drm_device_get(void); +void imx_drm_device_put(void); +int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, + u32 interface_pix_fmt); +void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper); + +struct device_node; + +int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder, + struct drm_crtc *crtc); +int imx_drm_encoder_add_possible_crtcs(struct imx_drm_encoder *imx_drm_encoder, + struct device_node *np); + +#endif /* _IMX_DRM_H_ */ diff --git a/drivers/staging/imx-drm/imx-fb.c b/drivers/staging/imx-drm/imx-fb.c new file mode 100644 index 000000000000..03a7b4e14f67 --- /dev/null +++ b/drivers/staging/imx-drm/imx-fb.c @@ -0,0 +1,47 @@ +/* + * i.MX drm driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that 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. + * + */ +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "imx-drm.h" + +static struct drm_mode_config_funcs imx_drm_mode_config_funcs = { + .fb_create = drm_fb_cma_create, +}; + +void imx_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 64; + dev->mode_config.min_height = 64; + + /* + * set max width and height as default value(4096x4096). + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &imx_drm_mode_config_funcs; +} diff --git a/drivers/staging/imx-drm/imx-fbdev.c b/drivers/staging/imx-drm/imx-fbdev.c new file mode 100644 index 000000000000..8331739c3d08 --- /dev/null +++ b/drivers/staging/imx-drm/imx-fbdev.c @@ -0,0 +1,74 @@ +/* + * i.MX drm driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that 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. + * + */ +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "imx-drm.h" + +#define MAX_CONNECTOR 4 +#define PREFERRED_BPP 16 + +static struct drm_fbdev_cma *fbdev_cma; + +static int legacyfb_depth = 16; + +module_param(legacyfb_depth, int, 0444); + +static int __init imx_fb_helper_init(void) +{ + struct drm_device *drm = imx_drm_device_get(); + + if (!drm) + return -EINVAL; + + if (legacyfb_depth != 16 && legacyfb_depth != 32) { + pr_warn("i.MX legacyfb: invalid legacyfb_depth setting. defaulting to 16bpp\n"); + legacyfb_depth = 16; + } + + fbdev_cma = drm_fbdev_cma_init(drm, legacyfb_depth, + drm->mode_config.num_crtc, MAX_CONNECTOR); + + if (IS_ERR(fbdev_cma)) { + imx_drm_device_put(); + return PTR_ERR(fbdev_cma); + } + + imx_drm_fb_helper_set(fbdev_cma); + + return 0; +} + +static void __exit imx_fb_helper_exit(void) +{ + imx_drm_fb_helper_set(NULL); + drm_fbdev_cma_fini(fbdev_cma); + imx_drm_device_put(); +} + +late_initcall(imx_fb_helper_init); +module_exit(imx_fb_helper_exit); + +MODULE_DESCRIPTION("Freescale i.MX legacy fb driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/ipu-v3/Makefile b/drivers/staging/imx-drm/ipu-v3/Makefile new file mode 100644 index 000000000000..28ed72e98a96 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += imx-ipu-v3.o + +imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h new file mode 100644 index 000000000000..74158dd73758 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h @@ -0,0 +1,318 @@ +/* + * Copyright 2005-2009 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU Lesser General + * Public License. You may obtain a copy of the GNU Lesser General + * Public License Version 2.1 or later at the following locations: + * + * http://www.opensource.org/licenses/lgpl-license.html + * http://www.gnu.org/copyleft/lgpl.html + */ + +#ifndef __DRM_IPU_H__ +#define __DRM_IPU_H__ + +#include <linux/types.h> +#include <linux/videodev2.h> +#include <linux/bitmap.h> +#include <linux/fb.h> +#include <linux/videodev2.h> + +struct ipu_soc; + +enum ipuv3_type { + IPUV3EX, + IPUV3M, + IPUV3H, +}; + +/* + * Bitfield of Display Interface signal polarities. + */ +struct ipu_di_signal_cfg { + unsigned datamask_en:1; + unsigned interlaced:1; + unsigned odd_field_first:1; + unsigned clksel_en:1; + unsigned clkidle_en:1; + unsigned data_pol:1; /* true = inverted */ + unsigned clk_pol:1; /* true = rising edge */ + unsigned enable_pol:1; + unsigned Hsync_pol:1; /* true = active high */ + unsigned Vsync_pol:1; + + u16 width; + u16 height; + u32 pixel_fmt; + u16 h_start_width; + u16 h_sync_width; + u16 h_end_width; + u16 v_start_width; + u16 v_sync_width; + u16 v_end_width; + u32 v_to_h_sync; + unsigned long pixelclock; +#define IPU_DI_CLKMODE_SYNC (1 << 0) +#define IPU_DI_CLKMODE_EXT (1 << 1) + unsigned long clkflags; +}; + +enum ipu_color_space { + IPUV3_COLORSPACE_RGB, + IPUV3_COLORSPACE_YUV, + IPUV3_COLORSPACE_UNKNOWN, +}; + +struct ipuv3_channel; + +enum ipu_channel_irq { + IPU_IRQ_EOF = 0, + IPU_IRQ_NFACK = 64, + IPU_IRQ_NFB4EOF = 128, + IPU_IRQ_EOS = 192, +}; + +int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, + enum ipu_channel_irq irq); + +#define IPU_IRQ_DP_SF_START (448 + 2) +#define IPU_IRQ_DP_SF_END (448 + 3) +#define IPU_IRQ_BG_SF_END IPU_IRQ_DP_SF_END, +#define IPU_IRQ_DC_FC_0 (448 + 8) +#define IPU_IRQ_DC_FC_1 (448 + 9) +#define IPU_IRQ_DC_FC_2 (448 + 10) +#define IPU_IRQ_DC_FC_3 (448 + 11) +#define IPU_IRQ_DC_FC_4 (448 + 12) +#define IPU_IRQ_DC_FC_6 (448 + 13) +#define IPU_IRQ_VSYNC_PRE_0 (448 + 14) +#define IPU_IRQ_VSYNC_PRE_1 (448 + 15) + +/* + * IPU Image DMA Controller (idmac) functions + */ +struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned channel); +void ipu_idmac_put(struct ipuv3_channel *); + +int ipu_idmac_enable_channel(struct ipuv3_channel *channel); +int ipu_idmac_disable_channel(struct ipuv3_channel *channel); + +void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, + bool doublebuffer); +void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num); + +/* + * IPU Display Controller (dc) functions + */ +struct ipu_dc; +struct ipu_di; +struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel); +void ipu_dc_put(struct ipu_dc *dc); +int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, + u32 pixel_fmt, u32 width); +void ipu_dc_enable_channel(struct ipu_dc *dc); +void ipu_dc_disable_channel(struct ipu_dc *dc); + +/* + * IPU Display Interface (di) functions + */ +struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp); +void ipu_di_put(struct ipu_di *); +int ipu_di_disable(struct ipu_di *); +int ipu_di_enable(struct ipu_di *); +int ipu_di_get_num(struct ipu_di *); +int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig); + +/* + * IPU Display Multi FIFO Controller (dmfc) functions + */ +struct dmfc_channel; +int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc); +void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); +int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, + unsigned long bandwidth_mbs, int burstsize); +void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc); +int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width); +struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); +void ipu_dmfc_put(struct dmfc_channel *dmfc); + +/* + * IPU Display Processor (dp) functions + */ +#define IPU_DP_FLOW_SYNC_BG 0 +#define IPU_DP_FLOW_SYNC_FG 1 +#define IPU_DP_FLOW_ASYNC0_BG 2 +#define IPU_DP_FLOW_ASYNC0_FG 3 +#define IPU_DP_FLOW_ASYNC1_BG 4 +#define IPU_DP_FLOW_ASYNC1_FG 5 + +struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow); +void ipu_dp_put(struct ipu_dp *); +int ipu_dp_enable_channel(struct ipu_dp *dp); +void ipu_dp_disable_channel(struct ipu_dp *dp); +int ipu_dp_setup_channel(struct ipu_dp *dp, + enum ipu_color_space in, enum ipu_color_space out); +int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos); +int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha, + bool bg_chan); + +#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size)) + +#define IPU_FIELD_UBO IPU_CPMEM_WORD(0, 46, 22) +#define IPU_FIELD_VBO IPU_CPMEM_WORD(0, 68, 22) +#define IPU_FIELD_IOX IPU_CPMEM_WORD(0, 90, 4) +#define IPU_FIELD_RDRW IPU_CPMEM_WORD(0, 94, 1) +#define IPU_FIELD_SO IPU_CPMEM_WORD(0, 113, 1) +#define IPU_FIELD_SLY IPU_CPMEM_WORD(1, 102, 14) +#define IPU_FIELD_SLUV IPU_CPMEM_WORD(1, 128, 14) + +#define IPU_FIELD_XV IPU_CPMEM_WORD(0, 0, 10) +#define IPU_FIELD_YV IPU_CPMEM_WORD(0, 10, 9) +#define IPU_FIELD_XB IPU_CPMEM_WORD(0, 19, 13) +#define IPU_FIELD_YB IPU_CPMEM_WORD(0, 32, 12) +#define IPU_FIELD_NSB_B IPU_CPMEM_WORD(0, 44, 1) +#define IPU_FIELD_CF IPU_CPMEM_WORD(0, 45, 1) +#define IPU_FIELD_SX IPU_CPMEM_WORD(0, 46, 12) +#define IPU_FIELD_SY IPU_CPMEM_WORD(0, 58, 11) +#define IPU_FIELD_NS IPU_CPMEM_WORD(0, 69, 10) +#define IPU_FIELD_SDX IPU_CPMEM_WORD(0, 79, 7) +#define IPU_FIELD_SM IPU_CPMEM_WORD(0, 86, 10) +#define IPU_FIELD_SCC IPU_CPMEM_WORD(0, 96, 1) +#define IPU_FIELD_SCE IPU_CPMEM_WORD(0, 97, 1) +#define IPU_FIELD_SDY IPU_CPMEM_WORD(0, 98, 7) +#define IPU_FIELD_SDRX IPU_CPMEM_WORD(0, 105, 1) +#define IPU_FIELD_SDRY IPU_CPMEM_WORD(0, 106, 1) +#define IPU_FIELD_BPP IPU_CPMEM_WORD(0, 107, 3) +#define IPU_FIELD_DEC_SEL IPU_CPMEM_WORD(0, 110, 2) +#define IPU_FIELD_DIM IPU_CPMEM_WORD(0, 112, 1) +#define IPU_FIELD_BNDM IPU_CPMEM_WORD(0, 114, 3) +#define IPU_FIELD_BM IPU_CPMEM_WORD(0, 117, 2) +#define IPU_FIELD_ROT IPU_CPMEM_WORD(0, 119, 1) +#define IPU_FIELD_HF IPU_CPMEM_WORD(0, 120, 1) +#define IPU_FIELD_VF IPU_CPMEM_WORD(0, 121, 1) +#define IPU_FIELD_THE IPU_CPMEM_WORD(0, 122, 1) +#define IPU_FIELD_CAP IPU_CPMEM_WORD(0, 123, 1) +#define IPU_FIELD_CAE IPU_CPMEM_WORD(0, 124, 1) +#define IPU_FIELD_FW IPU_CPMEM_WORD(0, 125, 13) +#define IPU_FIELD_FH IPU_CPMEM_WORD(0, 138, 12) +#define IPU_FIELD_EBA0 IPU_CPMEM_WORD(1, 0, 29) +#define IPU_FIELD_EBA1 IPU_CPMEM_WORD(1, 29, 29) +#define IPU_FIELD_ILO IPU_CPMEM_WORD(1, 58, 20) +#define IPU_FIELD_NPB IPU_CPMEM_WORD(1, 78, 7) +#define IPU_FIELD_PFS IPU_CPMEM_WORD(1, 85, 4) +#define IPU_FIELD_ALU IPU_CPMEM_WORD(1, 89, 1) +#define IPU_FIELD_ALBM IPU_CPMEM_WORD(1, 90, 3) +#define IPU_FIELD_ID IPU_CPMEM_WORD(1, 93, 2) +#define IPU_FIELD_TH IPU_CPMEM_WORD(1, 95, 7) +#define IPU_FIELD_SL IPU_CPMEM_WORD(1, 102, 14) +#define IPU_FIELD_WID0 IPU_CPMEM_WORD(1, 116, 3) +#define IPU_FIELD_WID1 IPU_CPMEM_WORD(1, 119, 3) +#define IPU_FIELD_WID2 IPU_CPMEM_WORD(1, 122, 3) +#define IPU_FIELD_WID3 IPU_CPMEM_WORD(1, 125, 3) +#define IPU_FIELD_OFS0 IPU_CPMEM_WORD(1, 128, 5) +#define IPU_FIELD_OFS1 IPU_CPMEM_WORD(1, 133, 5) +#define IPU_FIELD_OFS2 IPU_CPMEM_WORD(1, 138, 5) +#define IPU_FIELD_OFS3 IPU_CPMEM_WORD(1, 143, 5) +#define IPU_FIELD_SXYS IPU_CPMEM_WORD(1, 148, 1) +#define IPU_FIELD_CRE IPU_CPMEM_WORD(1, 149, 1) +#define IPU_FIELD_DEC_SEL2 IPU_CPMEM_WORD(1, 150, 1) + +struct ipu_cpmem_word { + u32 data[5]; + u32 res[3]; +}; + +struct ipu_ch_param { + struct ipu_cpmem_word word[2]; +}; + +void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v); +u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs); +struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel); +void ipu_ch_param_dump(struct ipu_ch_param __iomem *p); + +static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p) +{ + int i; + void __iomem *base = p; + + for (i = 0; i < sizeof(*p) / sizeof(u32); i++) + writel(0, base + i * sizeof(u32)); +} + +static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p, + int bufnum, dma_addr_t buf) +{ + if (bufnum) + ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3); + else + ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3); +} + +static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p, + int xres, int yres) +{ + ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1); + ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1); +} + +static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p, + int stride) +{ + ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1); +} + +void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel); + +struct ipu_rgb { + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; + int bits_per_pixel; +}; + +struct ipu_image { + struct v4l2_pix_format pix; + struct v4l2_rect rect; + dma_addr_t phys; +}; + +int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p, + int width); + +int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *, + struct ipu_rgb *rgb); + +static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p, + int stride) +{ + ipu_ch_param_write_field(p, IPU_FIELD_SO, 1); + ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8); + ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1); +}; + +void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format, + int stride, int height); +void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p, + u32 pixel_format, int stride, int u_offset, int v_offset); +int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat); +int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, + struct ipu_image *image); + +enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat); + +static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p, + int burstsize) +{ + ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1); +}; + +struct ipu_client_platformdata { + int di; + int dc; + int dp; + int dmfc; + int dma[2]; +}; + +#endif /* __DRM_IPU_H__ */ diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c new file mode 100644 index 000000000000..f381960f42b0 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -0,0 +1,1143 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ +#include <linux/module.h> +#include <linux/export.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/list.h> +#include <linux/irq.h> +#include <linux/of_device.h> +#include <asm/mach/irq.h> + +#include "imx-ipu-v3.h" +#include "ipu-prv.h" + +static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset) +{ + return readl(ipu->cm_reg + offset); +} + +static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset) +{ + writel(value, ipu->cm_reg + offset); +} + +static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset) +{ + return readl(ipu->idmac_reg + offset); +} + +static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value, + unsigned offset) +{ + writel(value, ipu->idmac_reg + offset); +} + +void ipu_srm_dp_sync_update(struct ipu_soc *ipu) +{ + u32 val; + + val = ipu_cm_read(ipu, IPU_SRM_PRI2); + val |= 0x8; + ipu_cm_write(ipu, val, IPU_SRM_PRI2); +} +EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); + +struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + + return ipu->cpmem_base + channel->num; +} +EXPORT_SYMBOL_GPL(ipu_get_cpmem); + +void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel); + u32 val; + + if (ipu->ipu_type == IPUV3EX) + ipu_ch_param_write_field(p, IPU_FIELD_ID, 1); + + val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num)); + val |= 1 << (channel->num % 32); + ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num)); +}; +EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority); + +void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v) +{ + u32 bit = (wbs >> 8) % 160; + u32 size = wbs & 0xff; + u32 word = (wbs >> 8) / 160; + u32 i = bit / 32; + u32 ofs = bit % 32; + u32 mask = (1 << size) - 1; + u32 val; + + pr_debug("%s %d %d %d\n", __func__, word, bit , size); + + val = readl(&base->word[word].data[i]); + val &= ~(mask << ofs); + val |= v << ofs; + writel(val, &base->word[word].data[i]); + + if ((bit + size - 1) / 32 > i) { + val = readl(&base->word[word].data[i + 1]); + val &= ~(mask >> (ofs ? (32 - ofs) : 0)); + val |= v >> (ofs ? (32 - ofs) : 0); + writel(val, &base->word[word].data[i + 1]); + } +} +EXPORT_SYMBOL_GPL(ipu_ch_param_write_field); + +u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs) +{ + u32 bit = (wbs >> 8) % 160; + u32 size = wbs & 0xff; + u32 word = (wbs >> 8) / 160; + u32 i = bit / 32; + u32 ofs = bit % 32; + u32 mask = (1 << size) - 1; + u32 val = 0; + + pr_debug("%s %d %d %d\n", __func__, word, bit , size); + + val = (readl(&base->word[word].data[i]) >> ofs) & mask; + + if ((bit + size - 1) / 32 > i) { + u32 tmp; + tmp = readl(&base->word[word].data[i + 1]); + tmp &= mask >> (ofs ? (32 - ofs) : 0); + val |= tmp << (ofs ? (32 - ofs) : 0); + } + + return val; +} +EXPORT_SYMBOL_GPL(ipu_ch_param_read_field); + +int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p, + struct ipu_rgb *rgb) +{ + int bpp = 0, npb = 0, ro, go, bo, to; + + ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset; + go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset; + bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset; + to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset; + + ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1); + ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro); + ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1); + ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go); + ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1); + ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo); + + if (rgb->transp.length) { + ipu_ch_param_write_field(p, IPU_FIELD_WID3, + rgb->transp.length - 1); + ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to); + } else { + ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7); + ipu_ch_param_write_field(p, IPU_FIELD_OFS3, + rgb->bits_per_pixel); + } + + switch (rgb->bits_per_pixel) { + case 32: + bpp = 0; + npb = 15; + break; + case 24: + bpp = 1; + npb = 19; + break; + case 16: + bpp = 3; + npb = 31; + break; + case 8: + bpp = 5; + npb = 63; + break; + default: + return -EINVAL; + } + ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp); + ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb); + ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */ + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb); + +int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p, + int width) +{ + int bpp = 0, npb = 0; + + switch (width) { + case 32: + bpp = 0; + npb = 15; + break; + case 24: + bpp = 1; + npb = 19; + break; + case 16: + bpp = 3; + npb = 31; + break; + case 8: + bpp = 5; + npb = 63; + break; + default: + return -EINVAL; + } + + ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp); + ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb); + ipu_ch_param_write_field(p, IPU_FIELD_PFS, 6); /* raw mode */ + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough); + +void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p, + u32 pixel_format, int stride, int u_offset, int v_offset) +{ + switch (pixel_format) { + case V4L2_PIX_FMT_YUV420: + ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1); + ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8); + ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8); + break; + } +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); + +void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format, + int stride, int height) +{ + int u_offset, v_offset; + int uv_stride = 0; + + switch (pixel_format) { + case V4L2_PIX_FMT_YUV420: + uv_stride = stride / 2; + u_offset = stride * height; + v_offset = u_offset + (uv_stride * height / 2); + ipu_cpmem_set_yuv_planar_full(p, V4L2_PIX_FMT_YUV420, stride, + u_offset, v_offset); + break; + } +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); + +static struct ipu_rgb def_rgb_32 = { + .red = { .offset = 16, .length = 8, }, + .green = { .offset = 8, .length = 8, }, + .blue = { .offset = 0, .length = 8, }, + .transp = { .offset = 24, .length = 8, }, + .bits_per_pixel = 32, +}; + +static struct ipu_rgb def_bgr_32 = { + .red = { .offset = 16, .length = 8, }, + .green = { .offset = 8, .length = 8, }, + .blue = { .offset = 0, .length = 8, }, + .transp = { .offset = 24, .length = 8, }, + .bits_per_pixel = 32, +}; + +static struct ipu_rgb def_rgb_24 = { + .red = { .offset = 0, .length = 8, }, + .green = { .offset = 8, .length = 8, }, + .blue = { .offset = 16, .length = 8, }, + .transp = { .offset = 0, .length = 0, }, + .bits_per_pixel = 24, +}; + +static struct ipu_rgb def_bgr_24 = { + .red = { .offset = 16, .length = 8, }, + .green = { .offset = 8, .length = 8, }, + .blue = { .offset = 0, .length = 8, }, + .transp = { .offset = 0, .length = 0, }, + .bits_per_pixel = 24, +}; + +static struct ipu_rgb def_rgb_16 = { + .red = { .offset = 11, .length = 5, }, + .green = { .offset = 5, .length = 6, }, + .blue = { .offset = 0, .length = 5, }, + .transp = { .offset = 0, .length = 0, }, + .bits_per_pixel = 16, +}; + +#define Y_OFFSET(pix, x, y) ((x) + pix->width * (y)) +#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * (y) / 4) + (x) / 2) +#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * pix->height / 4) + \ + (pix->width * (y) / 4) + (x) / 2) + +int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) +{ + switch (pixelformat) { + case V4L2_PIX_FMT_YUV420: + /* pix format */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2); + /* burst size */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63); + break; + case V4L2_PIX_FMT_UYVY: + /* bits/pixel */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); + /* pix format */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0xA); + /* burst size */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); + break; + case V4L2_PIX_FMT_YUYV: + /* bits/pixel */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); + /* pix format */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0x8); + /* burst size */ + ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); + break; + case V4L2_PIX_FMT_RGB32: + ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32); + break; + case V4L2_PIX_FMT_RGB565: + ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16); + break; + case V4L2_PIX_FMT_BGR32: + ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32); + break; + case V4L2_PIX_FMT_RGB24: + ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24); + break; + case V4L2_PIX_FMT_BGR24: + ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt); + +int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, + struct ipu_image *image) +{ + struct v4l2_pix_format *pix = &image->pix; + int y_offset, u_offset, v_offset; + + pr_debug("%s: resolution: %dx%d stride: %d\n", + __func__, pix->width, pix->height, + pix->bytesperline); + + ipu_cpmem_set_resolution(cpmem, image->rect.width, + image->rect.height); + ipu_cpmem_set_stride(cpmem, pix->bytesperline); + + ipu_cpmem_set_fmt(cpmem, pix->pixelformat); + + switch (pix->pixelformat) { + case V4L2_PIX_FMT_YUV420: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = U_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + v_offset = V_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + + ipu_cpmem_set_yuv_planar_full(cpmem, pix->pixelformat, + pix->bytesperline, u_offset, v_offset); + ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset); + break; + case V4L2_PIX_FMT_UYVY: + ipu_cpmem_set_buffer(cpmem, 0, image->phys + + image->rect.left * 2 + + image->rect.top * image->pix.bytesperline); + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + ipu_cpmem_set_buffer(cpmem, 0, image->phys + + image->rect.left * 4 + + image->rect.top * image->pix.bytesperline); + break; + case V4L2_PIX_FMT_RGB565: + ipu_cpmem_set_buffer(cpmem, 0, image->phys + + image->rect.left * 2 + + image->rect.top * image->pix.bytesperline); + break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + ipu_cpmem_set_buffer(cpmem, 0, image->phys + + image->rect.left * 3 + + image->rect.top * image->pix.bytesperline); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_image); + +enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat) +{ + switch (pixelformat) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + return IPUV3_COLORSPACE_YUV; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB565: + return IPUV3_COLORSPACE_RGB; + default: + return IPUV3_COLORSPACE_UNKNOWN; + } +} +EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace); + +struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num) +{ + struct ipuv3_channel *channel; + + dev_dbg(ipu->dev, "%s %d\n", __func__, num); + + if (num > 63) + return ERR_PTR(-ENODEV); + + mutex_lock(&ipu->channel_lock); + + channel = &ipu->channel[num]; + + if (channel->busy) { + channel = ERR_PTR(-EBUSY); + goto out; + } + + channel->busy = 1; + channel->num = num; + +out: + mutex_unlock(&ipu->channel_lock); + + return channel; +} +EXPORT_SYMBOL_GPL(ipu_idmac_get); + +void ipu_idmac_put(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + + dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num); + + mutex_lock(&ipu->channel_lock); + + channel->busy = 0; + + mutex_unlock(&ipu->channel_lock); +} +EXPORT_SYMBOL_GPL(ipu_idmac_put); + +#define idma_mask(ch) (1 << (ch & 0x1f)) + +void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, + bool doublebuffer) +{ + struct ipu_soc *ipu = channel->ipu; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&ipu->lock, flags); + + reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num)); + if (doublebuffer) + reg |= idma_mask(channel->num); + else + reg &= ~idma_mask(channel->num); + ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num)); + + spin_unlock_irqrestore(&ipu->lock, flags); +} +EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer); + +int ipu_module_enable(struct ipu_soc *ipu, u32 mask) +{ + unsigned long lock_flags; + u32 val; + + spin_lock_irqsave(&ipu->lock, lock_flags); + + val = ipu_cm_read(ipu, IPU_DISP_GEN); + + if (mask & IPU_CONF_DI0_EN) + val |= IPU_DI0_COUNTER_RELEASE; + if (mask & IPU_CONF_DI1_EN) + val |= IPU_DI1_COUNTER_RELEASE; + + ipu_cm_write(ipu, val, IPU_DISP_GEN); + + val = ipu_cm_read(ipu, IPU_CONF); + val |= mask; + ipu_cm_write(ipu, val, IPU_CONF); + + spin_unlock_irqrestore(&ipu->lock, lock_flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_module_enable); + +int ipu_module_disable(struct ipu_soc *ipu, u32 mask) +{ + unsigned long lock_flags; + u32 val; + + spin_lock_irqsave(&ipu->lock, lock_flags); + + val = ipu_cm_read(ipu, IPU_CONF); + val &= ~mask; + ipu_cm_write(ipu, val, IPU_CONF); + + val = ipu_cm_read(ipu, IPU_DISP_GEN); + + if (mask & IPU_CONF_DI0_EN) + val &= ~IPU_DI0_COUNTER_RELEASE; + if (mask & IPU_CONF_DI1_EN) + val &= ~IPU_DI1_COUNTER_RELEASE; + + ipu_cm_write(ipu, val, IPU_DISP_GEN); + + spin_unlock_irqrestore(&ipu->lock, lock_flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_module_disable); + +void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num) +{ + struct ipu_soc *ipu = channel->ipu; + unsigned int chno = channel->num; + unsigned long flags; + + spin_lock_irqsave(&ipu->lock, flags); + + /* Mark buffer as ready. */ + if (buf_num == 0) + ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno)); + else + ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno)); + + spin_unlock_irqrestore(&ipu->lock, flags); +} +EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer); + +int ipu_idmac_enable_channel(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + u32 val; + unsigned long flags; + + spin_lock_irqsave(&ipu->lock, flags); + + val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num)); + val |= idma_mask(channel->num); + ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); + + spin_unlock_irqrestore(&ipu->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel); + +int ipu_idmac_disable_channel(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + u32 val; + unsigned long flags; + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(50); + while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) & + idma_mask(channel->num)) { + if (time_after(jiffies, timeout)) { + dev_warn(ipu->dev, "disabling busy idmac channel %d\n", + channel->num); + break; + } + cpu_relax(); + } + + spin_lock_irqsave(&ipu->lock, flags); + + /* Disable DMA channel(s) */ + val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num)); + val &= ~idma_mask(channel->num); + ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); + + /* Set channel buffers NOT to be ready */ + ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */ + + if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) & + idma_mask(channel->num)) { + ipu_cm_write(ipu, idma_mask(channel->num), + IPU_CHA_BUF0_RDY(channel->num)); + } + + if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) & + idma_mask(channel->num)) { + ipu_cm_write(ipu, idma_mask(channel->num), + IPU_CHA_BUF1_RDY(channel->num)); + } + + ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */ + + /* Reset the double buffer */ + val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num)); + val &= ~idma_mask(channel->num); + ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num)); + + spin_unlock_irqrestore(&ipu->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel); + +static int ipu_reset(struct ipu_soc *ipu) +{ + unsigned long timeout; + + ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST); + + timeout = jiffies + msecs_to_jiffies(1000); + while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) { + if (time_after(jiffies, timeout)) + return -ETIME; + cpu_relax(); + } + + mdelay(300); + + return 0; +} + +struct ipu_devtype { + const char *name; + unsigned long cm_ofs; + unsigned long cpmem_ofs; + unsigned long srm_ofs; + unsigned long tpm_ofs; + unsigned long disp0_ofs; + unsigned long disp1_ofs; + unsigned long dc_tmpl_ofs; + unsigned long vdi_ofs; + enum ipuv3_type type; +}; + +static struct ipu_devtype ipu_type_imx51 = { + .name = "IPUv3EX", + .cm_ofs = 0x1e000000, + .cpmem_ofs = 0x1f000000, + .srm_ofs = 0x1f040000, + .tpm_ofs = 0x1f060000, + .disp0_ofs = 0x1e040000, + .disp1_ofs = 0x1e048000, + .dc_tmpl_ofs = 0x1f080000, + .vdi_ofs = 0x1e068000, + .type = IPUV3EX, +}; + +static struct ipu_devtype ipu_type_imx53 = { + .name = "IPUv3M", + .cm_ofs = 0x06000000, + .cpmem_ofs = 0x07000000, + .srm_ofs = 0x07040000, + .tpm_ofs = 0x07060000, + .disp0_ofs = 0x06040000, + .disp1_ofs = 0x06048000, + .dc_tmpl_ofs = 0x07080000, + .vdi_ofs = 0x06068000, + .type = IPUV3M, +}; + +static struct ipu_devtype ipu_type_imx6q = { + .name = "IPUv3H", + .cm_ofs = 0x00200000, + .cpmem_ofs = 0x00300000, + .srm_ofs = 0x00340000, + .tpm_ofs = 0x00360000, + .disp0_ofs = 0x00240000, + .disp1_ofs = 0x00248000, + .dc_tmpl_ofs = 0x00380000, + .vdi_ofs = 0x00268000, + .type = IPUV3H, +}; + +static const struct of_device_id imx_ipu_dt_ids[] = { + { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, }, + { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, }, + { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids); + +static int ipu_submodules_init(struct ipu_soc *ipu, + struct platform_device *pdev, unsigned long ipu_base, + struct clk *ipu_clk) +{ + char *unit; + int ret; + struct device *dev = &pdev->dev; + const struct ipu_devtype *devtype = ipu->devtype; + + ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs, + IPU_CONF_DI0_EN, ipu_clk); + if (ret) { + unit = "di0"; + goto err_di_0; + } + + ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs, + IPU_CONF_DI1_EN, ipu_clk); + if (ret) { + unit = "di1"; + goto err_di_1; + } + + ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs + + IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs); + if (ret) { + unit = "dc_template"; + goto err_dc; + } + + ret = ipu_dmfc_init(ipu, dev, ipu_base + + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk); + if (ret) { + unit = "dmfc"; + goto err_dmfc; + } + + ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs); + if (ret) { + unit = "dp"; + goto err_dp; + } + + return 0; + +err_dp: + ipu_dmfc_exit(ipu); +err_dmfc: + ipu_dc_exit(ipu); +err_dc: + ipu_di_exit(ipu, 1); +err_di_1: + ipu_di_exit(ipu, 0); +err_di_0: + dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret); + return ret; +} + +static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) +{ + unsigned long status; + int i, bit, irq_base; + + for (i = 0; i < num_regs; i++) { + + status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i])); + status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i])); + + irq_base = ipu->irq_start + regs[i] * 32; + for_each_set_bit(bit, &status, 32) + generic_handle_irq(irq_base + bit); + } +} + +static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct ipu_soc *ipu = irq_desc_get_handler_data(desc); + const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14}; + struct irq_chip *chip = irq_get_chip(irq); + + chained_irq_enter(chip, desc); + + ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg)); + + chained_irq_exit(chip, desc); +} + +static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct ipu_soc *ipu = irq_desc_get_handler_data(desc); + const int int_reg[] = { 4, 5, 8, 9}; + struct irq_chip *chip = irq_get_chip(irq); + + chained_irq_enter(chip, desc); + + ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg)); + + chained_irq_exit(chip, desc); +} + +static void ipu_ack_irq(struct irq_data *d) +{ + struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); + unsigned int irq = d->irq - ipu->irq_start; + + ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32)); +} + +static void ipu_unmask_irq(struct irq_data *d) +{ + struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); + unsigned int irq = d->irq - ipu->irq_start; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&ipu->lock, flags); + + reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); + reg |= 1 << (irq % 32); + ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); + + spin_unlock_irqrestore(&ipu->lock, flags); +} + +static void ipu_mask_irq(struct irq_data *d) +{ + struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); + unsigned int irq = d->irq - ipu->irq_start; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&ipu->lock, flags); + + reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); + reg &= ~(1 << (irq % 32)); + ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); + + spin_unlock_irqrestore(&ipu->lock, flags); +} + +static struct irq_chip ipu_irq_chip = { + .name = "IPU", + .irq_ack = ipu_ack_irq, + .irq_mask = ipu_mask_irq, + .irq_unmask = ipu_unmask_irq, +}; + +int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, + enum ipu_channel_irq irq_type) +{ + return ipu->irq_start + irq_type + channel->num; +} +EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); + +static void ipu_submodules_exit(struct ipu_soc *ipu) +{ + ipu_dp_exit(ipu); + ipu_dmfc_exit(ipu); + ipu_dc_exit(ipu); + ipu_di_exit(ipu, 1); + ipu_di_exit(ipu, 0); +} + +static int platform_remove_devices_fn(struct device *dev, void *unused) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + +static void platform_device_unregister_children(struct platform_device *pdev) +{ + device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn); +} + +struct ipu_platform_reg { + struct ipu_client_platformdata pdata; + const char *name; +}; + +static const struct ipu_platform_reg client_reg[] = { + { + .pdata = { + .di = 0, + .dc = 5, + .dp = IPU_DP_FLOW_SYNC_BG, + .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC, + .dma[1] = -EINVAL, + }, + .name = "imx-ipuv3-crtc", + }, { + .pdata = { + .di = 1, + .dc = 1, + .dp = -EINVAL, + .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC, + .dma[1] = -EINVAL, + }, + .name = "imx-ipuv3-crtc", + }, +}; + +static int ipu_client_id; + +static int ipu_add_subdevice_pdata(struct device *dev, + const struct ipu_platform_reg *reg) +{ + struct platform_device *pdev; + + pdev = platform_device_register_data(dev, reg->name, ipu_client_id++, + ®->pdata, sizeof(struct ipu_platform_reg)); + + return pdev ? 0 : -EINVAL; +} + +static int ipu_add_client_devices(struct ipu_soc *ipu) +{ + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(client_reg); i++) { + const struct ipu_platform_reg *reg = &client_reg[i]; + ret = ipu_add_subdevice_pdata(ipu->dev, reg); + if (ret) + goto err_register; + } + + return 0; + +err_register: + platform_device_unregister_children(to_platform_device(ipu->dev)); + + return ret; +} + +static int ipu_irq_init(struct ipu_soc *ipu) +{ + int i; + + ipu->irq_start = irq_alloc_descs(-1, 0, IPU_NUM_IRQS, 0); + if (ipu->irq_start < 0) + return ipu->irq_start; + + for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { + irq_set_chip_and_handler(i, &ipu_irq_chip, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + irq_set_chip_data(i, ipu); + } + + irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); + irq_set_handler_data(ipu->irq_sync, ipu); + irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler); + irq_set_handler_data(ipu->irq_err, ipu); + + return 0; +} + +static void ipu_irq_exit(struct ipu_soc *ipu) +{ + int i; + + irq_set_chained_handler(ipu->irq_err, NULL); + irq_set_handler_data(ipu->irq_err, NULL); + irq_set_chained_handler(ipu->irq_sync, NULL); + irq_set_handler_data(ipu->irq_sync, NULL); + + for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { + set_irq_flags(i, 0); + irq_set_chip(i, NULL); + irq_set_chip_data(i, NULL); + } + + irq_free_descs(ipu->irq_start, IPU_NUM_IRQS); +} + +static int __devinit ipu_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(imx_ipu_dt_ids, &pdev->dev); + struct ipu_soc *ipu; + struct resource *res; + unsigned long ipu_base; + int i, ret, irq_sync, irq_err; + const struct ipu_devtype *devtype; + + devtype = of_id->data; + + dev_info(&pdev->dev, "Initializing %s\n", devtype->name); + + irq_sync = platform_get_irq(pdev, 0); + irq_err = platform_get_irq(pdev, 1); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + dev_info(&pdev->dev, "irq_sync: %d irq_err: %d\n", + irq_sync, irq_err); + + if (!res || irq_sync < 0 || irq_err < 0) + return -ENODEV; + + ipu_base = res->start; + + ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL); + if (!ipu) + return -ENODEV; + + for (i = 0; i < 64; i++) + ipu->channel[i].ipu = ipu; + ipu->devtype = devtype; + ipu->ipu_type = devtype->type; + + spin_lock_init(&ipu->lock); + mutex_init(&ipu->channel_lock); + + dev_info(&pdev->dev, "cm_reg: 0x%08lx\n", + ipu_base + devtype->cm_ofs); + dev_info(&pdev->dev, "idmac: 0x%08lx\n", + ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS); + dev_info(&pdev->dev, "cpmem: 0x%08lx\n", + ipu_base + devtype->cpmem_ofs); + dev_info(&pdev->dev, "disp0: 0x%08lx\n", + ipu_base + devtype->disp0_ofs); + dev_info(&pdev->dev, "disp1: 0x%08lx\n", + ipu_base + devtype->disp1_ofs); + dev_info(&pdev->dev, "srm: 0x%08lx\n", + ipu_base + devtype->srm_ofs); + dev_info(&pdev->dev, "tpm: 0x%08lx\n", + ipu_base + devtype->tpm_ofs); + dev_info(&pdev->dev, "dc: 0x%08lx\n", + ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS); + dev_info(&pdev->dev, "ic: 0x%08lx\n", + ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS); + dev_info(&pdev->dev, "dmfc: 0x%08lx\n", + ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS); + dev_info(&pdev->dev, "vdi: 0x%08lx\n", + ipu_base + devtype->vdi_ofs); + + ipu->cm_reg = devm_ioremap(&pdev->dev, + ipu_base + devtype->cm_ofs, PAGE_SIZE); + ipu->idmac_reg = devm_ioremap(&pdev->dev, + ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS, + PAGE_SIZE); + ipu->cpmem_base = devm_ioremap(&pdev->dev, + ipu_base + devtype->cpmem_ofs, PAGE_SIZE); + + if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) { + ret = -ENOMEM; + goto failed_ioremap; + } + + ipu->clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(ipu->clk)) { + ret = PTR_ERR(ipu->clk); + dev_err(&pdev->dev, "clk_get failed with %d", ret); + goto failed_clk_get; + } + + platform_set_drvdata(pdev, ipu); + + clk_prepare_enable(ipu->clk); + + ipu->dev = &pdev->dev; + ipu->irq_sync = irq_sync; + ipu->irq_err = irq_err; + + ret = ipu_irq_init(ipu); + if (ret) + goto out_failed_irq; + + ipu_reset(ipu); + + /* Set MCU_T to divide MCU access window into 2 */ + ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), + IPU_DISP_GEN); + + ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk); + if (ret) + goto failed_submodules_init; + + ret = ipu_add_client_devices(ipu); + if (ret) { + dev_err(&pdev->dev, "adding client devices failed with %d\n", + ret); + goto failed_add_clients; + } + + return 0; + +failed_add_clients: + ipu_submodules_exit(ipu); +failed_submodules_init: + ipu_irq_exit(ipu); +out_failed_irq: + clk_disable_unprepare(ipu->clk); +failed_clk_get: +failed_ioremap: + return ret; +} + +static int __devexit ipu_remove(struct platform_device *pdev) +{ + struct ipu_soc *ipu = platform_get_drvdata(pdev); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + platform_device_unregister_children(pdev); + ipu_submodules_exit(ipu); + ipu_irq_exit(ipu); + + clk_disable_unprepare(ipu->clk); + + return 0; +} + +static struct platform_driver imx_ipu_driver = { + .driver = { + .name = "imx-ipuv3", + .of_match_table = imx_ipu_dt_ids, + }, + .probe = ipu_probe, + .remove = __devexit_p(ipu_remove), +}; + +module_platform_driver(imx_ipu_driver); + +MODULE_DESCRIPTION("i.MX IPU v3 driver"); +MODULE_AUTHOR("Sascha Hauer <[email protected]>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c new file mode 100644 index 000000000000..93c7579417be --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ + +#include <linux/export.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/io.h> + +#include "imx-ipu-v3.h" +#include "ipu-prv.h" + +#define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2) +#define DC_MAP_CONF_VAL(n) (0x144 + ((n) & ~0x1) * 2) + +#define DC_EVT_NF 0 +#define DC_EVT_NL 1 +#define DC_EVT_EOF 2 +#define DC_EVT_NFIELD 3 +#define DC_EVT_EOL 4 +#define DC_EVT_EOFIELD 5 +#define DC_EVT_NEW_ADDR 6 +#define DC_EVT_NEW_CHAN 7 +#define DC_EVT_NEW_DATA 8 + +#define DC_EVT_NEW_ADDR_W_0 0 +#define DC_EVT_NEW_ADDR_W_1 1 +#define DC_EVT_NEW_CHAN_W_0 2 +#define DC_EVT_NEW_CHAN_W_1 3 +#define DC_EVT_NEW_DATA_W_0 4 +#define DC_EVT_NEW_DATA_W_1 5 +#define DC_EVT_NEW_ADDR_R_0 6 +#define DC_EVT_NEW_ADDR_R_1 7 +#define DC_EVT_NEW_CHAN_R_0 8 +#define DC_EVT_NEW_CHAN_R_1 9 +#define DC_EVT_NEW_DATA_R_0 10 +#define DC_EVT_NEW_DATA_R_1 11 + +#define DC_WR_CH_CONF 0x0 +#define DC_WR_CH_ADDR 0x4 +#define DC_RL_CH(evt) (8 + ((evt) & ~0x1) * 2) + +#define DC_GEN 0xd4 +#define DC_DISP_CONF1(disp) (0xd8 + (disp) * 4) +#define DC_DISP_CONF2(disp) (0xe8 + (disp) * 4) +#define DC_STAT 0x1c8 + +#define WROD(lf) (0x18 | ((lf) << 1)) +#define WRG 0x01 + +#define SYNC_WAVE 0 + +#define DC_GEN_SYNC_1_6_SYNC (2 << 1) +#define DC_GEN_SYNC_PRIORITY_1 (1 << 7) + +#define DC_WR_CH_CONF_WORD_SIZE_8 (0 << 0) +#define DC_WR_CH_CONF_WORD_SIZE_16 (1 << 0) +#define DC_WR_CH_CONF_WORD_SIZE_24 (2 << 0) +#define DC_WR_CH_CONF_WORD_SIZE_32 (3 << 0) +#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i) (((i) & 0x1) << 3) +#define DC_WR_CH_CONF_DISP_ID_SERIAL (2 << 3) +#define DC_WR_CH_CONF_DISP_ID_ASYNC (3 << 4) +#define DC_WR_CH_CONF_FIELD_MODE (1 << 9) +#define DC_WR_CH_CONF_PROG_TYPE_NORMAL (4 << 5) +#define DC_WR_CH_CONF_PROG_TYPE_MASK (7 << 5) +#define DC_WR_CH_CONF_PROG_DI_ID (1 << 2) +#define DC_WR_CH_CONF_PROG_DISP_ID(i) (((i) & 0x1) << 3) + +#define IPU_DC_NUM_CHANNELS 10 + +struct ipu_dc_priv; + +enum ipu_dc_map { + IPU_DC_MAP_RGB24, + IPU_DC_MAP_RGB565, +}; + +struct ipu_dc { + /* The display interface number assigned to this dc channel */ + unsigned int di; + void __iomem *base; + struct ipu_dc_priv *priv; + int chno; + bool in_use; +}; + +struct ipu_dc_priv { + void __iomem *dc_reg; + void __iomem *dc_tmpl_reg; + struct ipu_soc *ipu; + struct device *dev; + struct ipu_dc channels[IPU_DC_NUM_CHANNELS]; + struct mutex mutex; +}; + +static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority) +{ + u32 reg; + + reg = readl(dc->base + DC_RL_CH(event)); + reg &= ~(0xffff << (16 * (event & 0x1))); + reg |= ((addr << 8) | priority) << (16 * (event & 0x1)); + writel(reg, dc->base + DC_RL_CH(event)); +} + +static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand, + int map, int wave, int glue, int sync) +{ + struct ipu_dc_priv *priv = dc->priv; + u32 reg; + int stop = 1; + + reg = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000); + writel(reg, priv->dc_tmpl_reg + word * 8); + reg = operand >> 12 | opcode << 4 | stop << 9; + writel(reg, priv->dc_tmpl_reg + word * 8 + 4); +} + +static int ipu_pixfmt_to_map(u32 fmt) +{ + switch (fmt) { + case V4L2_PIX_FMT_RGB24: + return IPU_DC_MAP_RGB24; + case V4L2_PIX_FMT_RGB565: + return IPU_DC_MAP_RGB565; + default: + return -EINVAL; + } +} + +int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, + u32 pixel_fmt, u32 width) +{ + struct ipu_dc_priv *priv = dc->priv; + u32 reg = 0, map; + + dc->di = ipu_di_get_num(di); + + map = ipu_pixfmt_to_map(pixel_fmt); + if (map < 0) { + dev_dbg(priv->dev, "IPU_DISP: No MAP\n"); + return -EINVAL; + } + + if (interlaced) { + dc_link_event(dc, DC_EVT_NL, 0, 3); + dc_link_event(dc, DC_EVT_EOL, 0, 2); + dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1); + + /* Init template microcode */ + dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8); + } else { + if (dc->di) { + dc_link_event(dc, DC_EVT_NL, 2, 3); + dc_link_event(dc, DC_EVT_EOL, 3, 2); + dc_link_event(dc, DC_EVT_NEW_DATA, 4, 1); + /* Init template microcode */ + dc_write_tmpl(dc, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5); + dc_write_tmpl(dc, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5); + dc_write_tmpl(dc, 4, WROD(0), 0, map, SYNC_WAVE, 0, 5); + } else { + dc_link_event(dc, DC_EVT_NL, 5, 3); + dc_link_event(dc, DC_EVT_EOL, 6, 2); + dc_link_event(dc, DC_EVT_NEW_DATA, 7, 1); + /* Init template microcode */ + dc_write_tmpl(dc, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5); + dc_write_tmpl(dc, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5); + dc_write_tmpl(dc, 7, WROD(0), 0, map, SYNC_WAVE, 0, 5); + } + } + dc_link_event(dc, DC_EVT_NF, 0, 0); + dc_link_event(dc, DC_EVT_NFIELD, 0, 0); + dc_link_event(dc, DC_EVT_EOF, 0, 0); + dc_link_event(dc, DC_EVT_EOFIELD, 0, 0); + dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0); + dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0); + + reg = readl(dc->base + DC_WR_CH_CONF); + if (interlaced) + reg |= DC_WR_CH_CONF_FIELD_MODE; + else + reg &= ~DC_WR_CH_CONF_FIELD_MODE; + writel(reg, dc->base + DC_WR_CH_CONF); + + writel(0x0, dc->base + DC_WR_CH_ADDR); + writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di)); + + ipu_module_enable(priv->ipu, IPU_CONF_DC_EN); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dc_init_sync); + +void ipu_dc_enable_channel(struct ipu_dc *dc) +{ + int di; + u32 reg; + + di = dc->di; + + reg = readl(dc->base + DC_WR_CH_CONF); + reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL; + writel(reg, dc->base + DC_WR_CH_CONF); +} +EXPORT_SYMBOL_GPL(ipu_dc_enable_channel); + +void ipu_dc_disable_channel(struct ipu_dc *dc) +{ + struct ipu_dc_priv *priv = dc->priv; + u32 val; + int irq = 0, timeout = 50; + + if (dc->chno == 1) + irq = IPU_IRQ_DC_FC_1; + else if (dc->chno == 5) + irq = IPU_IRQ_DP_SF_END; + else + return; + + /* should wait for the interrupt here */ + mdelay(50); + + if (dc->di == 0) + val = 0x00000002; + else + val = 0x00000020; + + /* Wait for DC triple buffer to empty */ + while ((readl(priv->dc_reg + DC_STAT) & val) != val) { + msleep(2); + timeout -= 2; + if (timeout <= 0) + break; + } + + val = readl(dc->base + DC_WR_CH_CONF); + val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK; + writel(val, dc->base + DC_WR_CH_CONF); +} +EXPORT_SYMBOL_GPL(ipu_dc_disable_channel); + +static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map, + int byte_num, int offset, int mask) +{ + int ptr = map * 3 + byte_num; + u32 reg; + + reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr)); + reg &= ~(0xffff << (16 * (ptr & 0x1))); + reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1)); + writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr)); + + reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map)); + reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num))); + reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num)); + writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map)); +} + +static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map) +{ + u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map)); + + writel(reg & ~(0xffff << (16 * (map & 0x1))), + priv->dc_reg + DC_MAP_CONF_PTR(map)); +} + +struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel) +{ + struct ipu_dc_priv *priv = ipu->dc_priv; + struct ipu_dc *dc; + + if (channel >= IPU_DC_NUM_CHANNELS) + return ERR_PTR(-ENODEV); + + dc = &priv->channels[channel]; + + mutex_lock(&priv->mutex); + + if (dc->in_use) { + mutex_unlock(&priv->mutex); + return ERR_PTR(-EBUSY); + } + + dc->in_use = 1; + + mutex_unlock(&priv->mutex); + + return dc; +} +EXPORT_SYMBOL_GPL(ipu_dc_get); + +void ipu_dc_put(struct ipu_dc *dc) +{ + struct ipu_dc_priv *priv = dc->priv; + + mutex_lock(&priv->mutex); + dc->in_use = 0; + mutex_unlock(&priv->mutex); +} +EXPORT_SYMBOL_GPL(ipu_dc_put); + +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, + unsigned long base, unsigned long template_base) +{ + struct ipu_dc_priv *priv; + static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c, + 0x78, 0, 0x94, 0xb4}; + int i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->mutex); + + priv->dev = dev; + priv->ipu = ipu; + priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE); + priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE); + if (!priv->dc_reg || !priv->dc_tmpl_reg) + return -ENOMEM; + + for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) { + priv->channels[i].chno = i; + priv->channels[i].priv = priv; + priv->channels[i].base = priv->dc_reg + channel_offsets[i]; + } + + writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) | + DC_WR_CH_CONF_PROG_DI_ID, + priv->channels[1].base + DC_WR_CH_CONF); + writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0), + priv->channels[5].base + DC_WR_CH_CONF); + + writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1, priv->dc_reg + DC_GEN); + + ipu->dc_priv = priv; + + dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n", + base, template_base); + + /* rgb24 */ + ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24); + ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */ + ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */ + ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */ + + /* rgb565 */ + ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565); + ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */ + ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */ + ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */ + + return 0; +} + +void ipu_dc_exit(struct ipu_soc *ipu) +{ +} diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c new file mode 100644 index 000000000000..67d974f7be36 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ +#include <linux/export.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> + +#include "imx-ipu-v3.h" +#include "ipu-prv.h" + +struct ipu_di { + void __iomem *base; + int id; + u32 module; + struct clk *clk_di; /* display input clock */ + struct clk *clk_ipu; /* IPU bus clock */ + struct clk *clk_di_pixel; /* resulting pixel clock */ + struct clk_hw clk_hw_out; + char *clk_name; + bool inuse; + unsigned long clkflags; + struct ipu_soc *ipu; +}; + +static DEFINE_MUTEX(di_mutex); + +struct di_sync_config { + int run_count; + int run_src; + int offset_count; + int offset_src; + int repeat_count; + int cnt_clr_src; + int cnt_polarity_gen_en; + int cnt_polarity_clr_src; + int cnt_polarity_trigger_src; + int cnt_up; + int cnt_down; +}; + +enum di_pins { + DI_PIN11 = 0, + DI_PIN12 = 1, + DI_PIN13 = 2, + DI_PIN14 = 3, + DI_PIN15 = 4, + DI_PIN16 = 5, + DI_PIN17 = 6, + DI_PIN_CS = 7, + + DI_PIN_SER_CLK = 0, + DI_PIN_SER_RS = 1, +}; + +enum di_sync_wave { + DI_SYNC_NONE = 0, + DI_SYNC_CLK = 1, + DI_SYNC_INT_HSYNC = 2, + DI_SYNC_HSYNC = 3, + DI_SYNC_VSYNC = 4, + DI_SYNC_DE = 6, +}; + +#define SYNC_WAVE 0 + +#define DI_GENERAL 0x0000 +#define DI_BS_CLKGEN0 0x0004 +#define DI_BS_CLKGEN1 0x0008 +#define DI_SW_GEN0(gen) (0x000c + 4 * ((gen) - 1)) +#define DI_SW_GEN1(gen) (0x0030 + 4 * ((gen) - 1)) +#define DI_STP_REP(gen) (0x0148 + 4 * (((gen) - 1)/2)) +#define DI_SYNC_AS_GEN 0x0054 +#define DI_DW_GEN(gen) (0x0058 + 4 * (gen)) +#define DI_DW_SET(gen, set) (0x0088 + 4 * ((gen) + 0xc * (set))) +#define DI_SER_CONF 0x015c +#define DI_SSC 0x0160 +#define DI_POL 0x0164 +#define DI_AW0 0x0168 +#define DI_AW1 0x016c +#define DI_SCR_CONF 0x0170 +#define DI_STAT 0x0174 + +#define DI_SW_GEN0_RUN_COUNT(x) ((x) << 19) +#define DI_SW_GEN0_RUN_SRC(x) ((x) << 16) +#define DI_SW_GEN0_OFFSET_COUNT(x) ((x) << 3) +#define DI_SW_GEN0_OFFSET_SRC(x) ((x) << 0) + +#define DI_SW_GEN1_CNT_POL_GEN_EN(x) ((x) << 29) +#define DI_SW_GEN1_CNT_CLR_SRC(x) ((x) << 25) +#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x) ((x) << 12) +#define DI_SW_GEN1_CNT_POL_CLR_SRC(x) ((x) << 9) +#define DI_SW_GEN1_CNT_DOWN(x) ((x) << 16) +#define DI_SW_GEN1_CNT_UP(x) (x) +#define DI_SW_GEN1_AUTO_RELOAD (0x10000000) + +#define DI_DW_GEN_ACCESS_SIZE_OFFSET 24 +#define DI_DW_GEN_COMPONENT_SIZE_OFFSET 16 + +#define DI_GEN_POLARITY_1 (1 << 0) +#define DI_GEN_POLARITY_2 (1 << 1) +#define DI_GEN_POLARITY_3 (1 << 2) +#define DI_GEN_POLARITY_4 (1 << 3) +#define DI_GEN_POLARITY_5 (1 << 4) +#define DI_GEN_POLARITY_6 (1 << 5) +#define DI_GEN_POLARITY_7 (1 << 6) +#define DI_GEN_POLARITY_8 (1 << 7) +#define DI_GEN_POLARITY_DISP_CLK (1 << 17) +#define DI_GEN_DI_CLK_EXT (1 << 20) +#define DI_GEN_DI_VSYNC_EXT (1 << 21) + +#define DI_POL_DRDY_DATA_POLARITY (1 << 7) +#define DI_POL_DRDY_POLARITY_15 (1 << 4) + +#define DI_VSYNC_SEL_OFFSET 13 + +static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset) +{ + return readl(di->base + offset); +} + +static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset) +{ + writel(value, di->base + offset); +} + +static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate) +{ + u64 tmp = inrate; + int div; + + tmp *= 16; + + do_div(tmp, outrate); + + div = tmp; + + if (div < 0x10) + div = 0x10; + +#ifdef WTF_IS_THIS + /* + * Freescale has this in their Kernel. It is neither clear what + * it does nor why it does it + */ + if (div & 0x10) + div &= ~0x7; + else { + /* Round up divider if it gets us closer to desired pix clk */ + if ((div & 0xC) == 0xC) { + div += 0x10; + div &= ~0xF; + } + } +#endif + return div; +} + +static unsigned long clk_di_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); + unsigned long outrate; + u32 div = ipu_di_read(di, DI_BS_CLKGEN0); + + if (div < 0x10) + div = 0x10; + + outrate = (parent_rate / div) * 16; + + return outrate; +} + +static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); + unsigned long outrate; + int div; + u32 val; + + div = ipu_di_clk_calc_div(*prate, rate); + + outrate = (*prate / div) * 16; + + val = ipu_di_read(di, DI_GENERAL); + + if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2) + outrate = *prate / 2; + + dev_dbg(di->ipu->dev, + "%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n", + __func__, *prate, div, outrate, rate); + + return outrate; +} + +static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); + int div; + u32 clkgen0; + + clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff; + + div = ipu_di_clk_calc_div(parent_rate, rate); + + ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0); + + dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n", + __func__, parent_rate, rate, div); + return 0; +} + +static u8 clk_di_get_parent(struct clk_hw *hw) +{ + struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); + u32 val; + + val = ipu_di_read(di, DI_GENERAL); + + return val & DI_GEN_DI_CLK_EXT ? 1 : 0; +} + +static int clk_di_set_parent(struct clk_hw *hw, u8 index) +{ + struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out); + u32 val; + + val = ipu_di_read(di, DI_GENERAL); + + if (index) + val |= DI_GEN_DI_CLK_EXT; + else + val &= ~DI_GEN_DI_CLK_EXT; + + ipu_di_write(di, val, DI_GENERAL); + + return 0; +} + +static struct clk_ops clk_di_ops = { + .round_rate = clk_di_round_rate, + .set_rate = clk_di_set_rate, + .recalc_rate = clk_di_recalc_rate, + .set_parent = clk_di_set_parent, + .get_parent = clk_di_get_parent, +}; + +static void ipu_di_data_wave_config(struct ipu_di *di, + int wave_gen, + int access_size, int component_size) +{ + u32 reg; + reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) | + (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET); + ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); +} + +static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin, + int set, int up, int down) +{ + u32 reg; + + reg = ipu_di_read(di, DI_DW_GEN(wave_gen)); + reg &= ~(0x3 << (di_pin * 2)); + reg |= set << (di_pin * 2); + ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); + + ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set)); +} + +static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config, + int start, int count) +{ + u32 reg; + int i; + + for (i = 0; i < count; i++) { + struct di_sync_config *c = &config[i]; + int wave_gen = start + i + 1; + + if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) || + (c->repeat_count >= 0x1000) || + (c->cnt_up >= 0x400) || + (c->cnt_down >= 0x400)) { + dev_err(di->ipu->dev, "DI%d counters out of range.\n", + di->id); + return; + } + + reg = DI_SW_GEN0_RUN_COUNT(c->run_count) | + DI_SW_GEN0_RUN_SRC(c->run_src) | + DI_SW_GEN0_OFFSET_COUNT(c->offset_count) | + DI_SW_GEN0_OFFSET_SRC(c->offset_src); + ipu_di_write(di, reg, DI_SW_GEN0(wave_gen)); + + reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) | + DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) | + DI_SW_GEN1_CNT_POL_TRIGGER_SRC( + c->cnt_polarity_trigger_src) | + DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) | + DI_SW_GEN1_CNT_DOWN(c->cnt_down) | + DI_SW_GEN1_CNT_UP(c->cnt_up); + + /* Enable auto reload */ + if (c->repeat_count == 0) + reg |= DI_SW_GEN1_AUTO_RELOAD; + + ipu_di_write(di, reg, DI_SW_GEN1(wave_gen)); + + reg = ipu_di_read(di, DI_STP_REP(wave_gen)); + reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1))); + reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1)); + ipu_di_write(di, reg, DI_STP_REP(wave_gen)); + } +} + +static void ipu_di_sync_config_interlaced(struct ipu_di *di, + struct ipu_di_signal_cfg *sig) +{ + u32 h_total = sig->width + sig->h_sync_width + + sig->h_start_width + sig->h_end_width; + u32 v_total = sig->height + sig->v_sync_width + + sig->v_start_width + sig->v_end_width; + u32 reg; + struct di_sync_config cfg[] = { + { + .run_count = h_total / 2 - 1, + .run_src = DI_SYNC_CLK, + }, { + .run_count = h_total - 11, + .run_src = DI_SYNC_CLK, + .cnt_down = 4, + }, { + .run_count = v_total * 2 - 1, + .run_src = DI_SYNC_INT_HSYNC, + .offset_count = 1, + .offset_src = DI_SYNC_INT_HSYNC, + .cnt_down = 4, + }, { + .run_count = v_total / 2 - 1, + .run_src = DI_SYNC_HSYNC, + .offset_count = sig->v_start_width, + .offset_src = DI_SYNC_HSYNC, + .repeat_count = 2, + .cnt_clr_src = DI_SYNC_VSYNC, + }, { + .run_src = DI_SYNC_HSYNC, + .repeat_count = sig->height / 2, + .cnt_clr_src = 4, + }, { + .run_count = v_total - 1, + .run_src = DI_SYNC_HSYNC, + }, { + .run_count = v_total / 2 - 1, + .run_src = DI_SYNC_HSYNC, + .offset_count = 9, + .offset_src = DI_SYNC_HSYNC, + .repeat_count = 2, + .cnt_clr_src = DI_SYNC_VSYNC, + }, { + .run_src = DI_SYNC_CLK, + .offset_count = sig->h_start_width, + .offset_src = DI_SYNC_CLK, + .repeat_count = sig->width, + .cnt_clr_src = 5, + }, { + .run_count = v_total - 1, + .run_src = DI_SYNC_INT_HSYNC, + .offset_count = v_total / 2, + .offset_src = DI_SYNC_INT_HSYNC, + .cnt_clr_src = DI_SYNC_HSYNC, + .cnt_down = 4, + } + }; + + ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); + + /* set gentime select and tag sel */ + reg = ipu_di_read(di, DI_SW_GEN1(9)); + reg &= 0x1FFFFFFF; + reg |= (3 - 1) << 29 | 0x00008000; + ipu_di_write(di, reg, DI_SW_GEN1(9)); + + ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF); +} + +static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, + struct ipu_di_signal_cfg *sig, int div) +{ + u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width + + sig->h_end_width; + u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width + + sig->v_end_width; + struct di_sync_config cfg[] = { + { + .run_count = h_total - 1, + .run_src = DI_SYNC_CLK, + } , { + .run_count = h_total - 1, + .run_src = DI_SYNC_CLK, + .offset_count = div * sig->v_to_h_sync, + .offset_src = DI_SYNC_CLK, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_CLK, + .cnt_down = sig->h_sync_width * 2, + } , { + .run_count = v_total - 1, + .run_src = DI_SYNC_INT_HSYNC, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, + .cnt_down = sig->v_sync_width * 2, + } , { + .run_src = DI_SYNC_HSYNC, + .offset_count = sig->v_sync_width + sig->v_start_width, + .offset_src = DI_SYNC_HSYNC, + .repeat_count = sig->height, + .cnt_clr_src = DI_SYNC_VSYNC, + } , { + .run_src = DI_SYNC_CLK, + .offset_count = sig->h_sync_width + sig->h_start_width, + .offset_src = DI_SYNC_CLK, + .repeat_count = sig->width, + .cnt_clr_src = 5, + } , { + /* unused */ + } , { + /* unused */ + } , { + /* unused */ + } , { + /* unused */ + }, + }; + + ipu_di_write(di, v_total - 1, DI_SCR_CONF); + ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); +} + +int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) +{ + u32 reg; + u32 di_gen, vsync_cnt; + u32 div; + u32 h_total, v_total; + int ret; + unsigned long round; + struct clk *parent; + + dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", + di->id, sig->width, sig->height); + + if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0)) + return -EINVAL; + + if (sig->clkflags & IPU_DI_CLKMODE_EXT) + parent = di->clk_di; + else + parent = di->clk_ipu; + + ret = clk_set_parent(di->clk_di_pixel, parent); + if (ret) { + dev_err(di->ipu->dev, + "setting pixel clock to parent %s failed with %d\n", + __clk_get_name(parent), ret); + return ret; + } + + if (sig->clkflags & IPU_DI_CLKMODE_SYNC) + round = clk_get_rate(parent); + else + round = clk_round_rate(di->clk_di_pixel, sig->pixelclock); + + ret = clk_set_rate(di->clk_di_pixel, round); + + h_total = sig->width + sig->h_sync_width + sig->h_start_width + + sig->h_end_width; + v_total = sig->height + sig->v_sync_width + sig->v_start_width + + sig->v_end_width; + + mutex_lock(&di_mutex); + + div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff; + div = div / 16; /* Now divider is integer portion */ + + /* Setup pixel clock timing */ + /* Down time is half of period */ + ipu_di_write(di, (div << 16), DI_BS_CLKGEN1); + + ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1); + ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2); + + di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT; + di_gen |= DI_GEN_DI_VSYNC_EXT; + + if (sig->interlaced) { + ipu_di_sync_config_interlaced(di, sig); + + /* set y_sel = 1 */ + di_gen |= 0x10000000; + di_gen |= DI_GEN_POLARITY_5; + di_gen |= DI_GEN_POLARITY_8; + + vsync_cnt = 7; + + if (sig->Hsync_pol) + di_gen |= DI_GEN_POLARITY_3; + if (sig->Vsync_pol) + di_gen |= DI_GEN_POLARITY_2; + } else { + ipu_di_sync_config_noninterlaced(di, sig, div); + + vsync_cnt = 3; + + if (sig->Hsync_pol) + di_gen |= DI_GEN_POLARITY_2; + if (sig->Vsync_pol) + di_gen |= DI_GEN_POLARITY_3; + } + + if (!sig->clk_pol) + di_gen |= DI_GEN_POLARITY_DISP_CLK; + + ipu_di_write(di, di_gen, DI_GENERAL); + + ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002, + DI_SYNC_AS_GEN); + + reg = ipu_di_read(di, DI_POL); + reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15); + + if (sig->enable_pol) + reg |= DI_POL_DRDY_POLARITY_15; + if (sig->data_pol) + reg |= DI_POL_DRDY_DATA_POLARITY; + + ipu_di_write(di, reg, DI_POL); + + mutex_unlock(&di_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel); + +int ipu_di_enable(struct ipu_di *di) +{ + clk_prepare_enable(di->clk_di_pixel); + + ipu_module_enable(di->ipu, di->module); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_di_enable); + +int ipu_di_disable(struct ipu_di *di) +{ + ipu_module_disable(di->ipu, di->module); + + clk_disable_unprepare(di->clk_di_pixel); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_di_disable); + +int ipu_di_get_num(struct ipu_di *di) +{ + return di->id; +} +EXPORT_SYMBOL_GPL(ipu_di_get_num); + +static DEFINE_MUTEX(ipu_di_lock); + +struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp) +{ + struct ipu_di *di; + + if (disp > 1) + return ERR_PTR(-EINVAL); + + di = ipu->di_priv[disp]; + + mutex_lock(&ipu_di_lock); + + if (di->inuse) { + di = ERR_PTR(-EBUSY); + goto out; + } + + di->inuse = true; +out: + mutex_unlock(&ipu_di_lock); + + return di; +} +EXPORT_SYMBOL_GPL(ipu_di_get); + +void ipu_di_put(struct ipu_di *di) +{ + mutex_lock(&ipu_di_lock); + + di->inuse = false; + + mutex_unlock(&ipu_di_lock); +} +EXPORT_SYMBOL_GPL(ipu_di_put); + +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id, + unsigned long base, + u32 module, struct clk *clk_ipu) +{ + struct ipu_di *di; + int ret; + const char *di_parent[2]; + struct clk_init_data init = { + .ops = &clk_di_ops, + .num_parents = 2, + .flags = 0, + }; + + if (id > 1) + return -ENODEV; + + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) + return -ENOMEM; + + ipu->di_priv[id] = di; + + di->clk_di = devm_clk_get(dev, id ? "di1" : "di0"); + if (IS_ERR(di->clk_di)) + return PTR_ERR(di->clk_di); + + di->module = module; + di->id = id; + di->clk_ipu = clk_ipu; + di->base = devm_ioremap(dev, base, PAGE_SIZE); + if (!di->base) + return -ENOMEM; + + di_parent[0] = __clk_get_name(di->clk_ipu); + di_parent[1] = __clk_get_name(di->clk_di); + + ipu_di_write(di, 0x10, DI_BS_CLKGEN0); + + init.parent_names = (const char **)&di_parent; + di->clk_name = kasprintf(GFP_KERNEL, "%s_di%d_pixel", + dev_name(dev), id); + if (!di->clk_name) + return -ENOMEM; + + init.name = di->clk_name; + + di->clk_hw_out.init = &init; + di->clk_di_pixel = clk_register(dev, &di->clk_hw_out); + + if (IS_ERR(di->clk_di_pixel)) { + ret = PTR_ERR(di->clk_di_pixel); + goto failed_clk_register; + } + + dev_info(dev, "DI%d base: 0x%08lx remapped to %p\n", + id, base, di->base); + di->inuse = false; + di->ipu = ipu; + + return 0; + +failed_clk_register: + + kfree(di->clk_name); + + return ret; +} + +void ipu_di_exit(struct ipu_soc *ipu, int id) +{ + struct ipu_di *di = ipu->di_priv[id]; + + clk_unregister(di->clk_di_pixel); + kfree(di->clk_name); +} diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c new file mode 100644 index 000000000000..91821bc30f41 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ +#include <linux/export.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/io.h> + +#include "imx-ipu-v3.h" +#include "ipu-prv.h" + +#define DMFC_RD_CHAN 0x0000 +#define DMFC_WR_CHAN 0x0004 +#define DMFC_WR_CHAN_DEF 0x0008 +#define DMFC_DP_CHAN 0x000c +#define DMFC_DP_CHAN_DEF 0x0010 +#define DMFC_GENERAL1 0x0014 +#define DMFC_GENERAL2 0x0018 +#define DMFC_IC_CTRL 0x001c +#define DMFC_STAT 0x0020 + +#define DMFC_WR_CHAN_1_28 0 +#define DMFC_WR_CHAN_2_41 8 +#define DMFC_WR_CHAN_1C_42 16 +#define DMFC_WR_CHAN_2C_43 24 + +#define DMFC_DP_CHAN_5B_23 0 +#define DMFC_DP_CHAN_5F_27 8 +#define DMFC_DP_CHAN_6B_24 16 +#define DMFC_DP_CHAN_6F_29 24 + +#define DMFC_FIFO_SIZE_64 (3 << 3) +#define DMFC_FIFO_SIZE_128 (2 << 3) +#define DMFC_FIFO_SIZE_256 (1 << 3) +#define DMFC_FIFO_SIZE_512 (0 << 3) + +#define DMFC_SEGMENT(x) ((x & 0x7) << 0) +#define DMFC_BURSTSIZE_128 (0 << 6) +#define DMFC_BURSTSIZE_64 (1 << 6) +#define DMFC_BURSTSIZE_32 (2 << 6) +#define DMFC_BURSTSIZE_16 (3 << 6) + +struct dmfc_channel_data { + int ipu_channel; + unsigned long channel_reg; + unsigned long shift; + unsigned eot_shift; + unsigned max_fifo_lines; +}; + +static const struct dmfc_channel_data dmfcdata[] = { + { + .ipu_channel = 23, + .channel_reg = DMFC_DP_CHAN, + .shift = DMFC_DP_CHAN_5B_23, + .eot_shift = 20, + .max_fifo_lines = 3, + }, { + .ipu_channel = 24, + .channel_reg = DMFC_DP_CHAN, + .shift = DMFC_DP_CHAN_6B_24, + .eot_shift = 22, + .max_fifo_lines = 1, + }, { + .ipu_channel = 27, + .channel_reg = DMFC_DP_CHAN, + .shift = DMFC_DP_CHAN_5F_27, + .eot_shift = 21, + .max_fifo_lines = 2, + }, { + .ipu_channel = 28, + .channel_reg = DMFC_WR_CHAN, + .shift = DMFC_WR_CHAN_1_28, + .eot_shift = 16, + .max_fifo_lines = 2, + }, { + .ipu_channel = 29, + .channel_reg = DMFC_DP_CHAN, + .shift = DMFC_DP_CHAN_6F_29, + .eot_shift = 23, + .max_fifo_lines = 1, + }, +}; + +#define DMFC_NUM_CHANNELS ARRAY_SIZE(dmfcdata) + +struct ipu_dmfc_priv; + +struct dmfc_channel { + unsigned slots; + unsigned slotmask; + unsigned segment; + int burstsize; + struct ipu_soc *ipu; + struct ipu_dmfc_priv *priv; + const struct dmfc_channel_data *data; +}; + +struct ipu_dmfc_priv { + struct ipu_soc *ipu; + struct device *dev; + struct dmfc_channel channels[DMFC_NUM_CHANNELS]; + struct mutex mutex; + unsigned long bandwidth_per_slot; + void __iomem *base; + int use_count; +}; + +int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + mutex_lock(&priv->mutex); + + if (!priv->use_count) + ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN); + + priv->use_count++; + + mutex_unlock(&priv->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel); + +void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + + mutex_lock(&priv->mutex); + + priv->use_count--; + + if (!priv->use_count) + ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN); + + if (priv->use_count < 0) + priv->use_count = 0; + + mutex_unlock(&priv->mutex); +} +EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel); + +static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots, + int segment, int burstsize) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + u32 val, field; + + dev_dbg(priv->dev, + "dmfc: using %d slots starting from segment %d for IPU channel %d\n", + slots, segment, dmfc->data->ipu_channel); + + if (!dmfc) + return -EINVAL; + + switch (slots) { + case 1: + field = DMFC_FIFO_SIZE_64; + break; + case 2: + field = DMFC_FIFO_SIZE_128; + break; + case 4: + field = DMFC_FIFO_SIZE_256; + break; + case 8: + field = DMFC_FIFO_SIZE_512; + break; + default: + return -EINVAL; + } + + switch (burstsize) { + case 16: + field |= DMFC_BURSTSIZE_16; + break; + case 32: + field |= DMFC_BURSTSIZE_32; + break; + case 64: + field |= DMFC_BURSTSIZE_64; + break; + case 128: + field |= DMFC_BURSTSIZE_128; + break; + } + + field |= DMFC_SEGMENT(segment); + + val = readl(priv->base + dmfc->data->channel_reg); + + val &= ~(0xff << dmfc->data->shift); + val |= field << dmfc->data->shift; + + writel(val, priv->base + dmfc->data->channel_reg); + + dmfc->slots = slots; + dmfc->segment = segment; + dmfc->burstsize = burstsize; + dmfc->slotmask = ((1 << slots) - 1) << segment; + + return 0; +} + +static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv, + unsigned long bandwidth) +{ + int slots = 1; + + while (slots * priv->bandwidth_per_slot < bandwidth) + slots *= 2; + + return slots; +} + +static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots) +{ + unsigned slotmask_need, slotmask_used = 0; + int i, segment = 0; + + slotmask_need = (1 << slots) - 1; + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) + slotmask_used |= priv->channels[i].slotmask; + + while (slotmask_need <= 0xff) { + if (!(slotmask_used & slotmask_need)) + return segment; + + slotmask_need <<= 1; + segment++; + } + + return -EBUSY; +} + +void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + int i; + + dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n", + dmfc->slots, dmfc->segment); + + mutex_lock(&priv->mutex); + + if (!dmfc->slots) + goto out; + + dmfc->slotmask = 0; + dmfc->slots = 0; + dmfc->segment = 0; + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) + priv->channels[i].slotmask = 0; + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) { + if (priv->channels[i].slots > 0) { + priv->channels[i].segment = + dmfc_find_slots(priv, priv->channels[i].slots); + priv->channels[i].slotmask = + ((1 << priv->channels[i].slots) - 1) << + priv->channels[i].segment; + } + } + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) { + if (priv->channels[i].slots > 0) + ipu_dmfc_setup_channel(&priv->channels[i], + priv->channels[i].slots, + priv->channels[i].segment, + priv->channels[i].burstsize); + } +out: + mutex_unlock(&priv->mutex); +} +EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth); + +int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, + unsigned long bandwidth_pixel_per_second, int burstsize) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second); + int segment = 0, ret = 0; + + dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n", + bandwidth_pixel_per_second / 1000000, + dmfc->data->ipu_channel); + + ipu_dmfc_free_bandwidth(dmfc); + + mutex_lock(&priv->mutex); + + if (slots > 8) { + ret = -EBUSY; + goto out; + } + + segment = dmfc_find_slots(priv, slots); + if (segment < 0) { + ret = -EBUSY; + goto out; + } + + ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize); + +out: + mutex_unlock(&priv->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth); + +int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width) +{ + struct ipu_dmfc_priv *priv = dmfc->priv; + u32 dmfc_gen1; + + dmfc_gen1 = readl(priv->base + DMFC_GENERAL1); + + if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines) + dmfc_gen1 |= 1 << dmfc->data->eot_shift; + else + dmfc_gen1 &= ~(1 << dmfc->data->eot_shift); + + writel(dmfc_gen1, priv->base + DMFC_GENERAL1); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel); + +struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel) +{ + struct ipu_dmfc_priv *priv = ipu->dmfc_priv; + int i; + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) + if (dmfcdata[i].ipu_channel == ipu_channel) + return &priv->channels[i]; + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL_GPL(ipu_dmfc_get); + +void ipu_dmfc_put(struct dmfc_channel *dmfc) +{ + ipu_dmfc_free_bandwidth(dmfc); +} +EXPORT_SYMBOL_GPL(ipu_dmfc_put); + +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, + struct clk *ipu_clk) +{ + struct ipu_dmfc_priv *priv; + int i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base = devm_ioremap(dev, base, PAGE_SIZE); + if (!priv->base) + return -ENOMEM; + + priv->dev = dev; + priv->ipu = ipu; + mutex_init(&priv->mutex); + + ipu->dmfc_priv = priv; + + for (i = 0; i < DMFC_NUM_CHANNELS; i++) { + priv->channels[i].priv = priv; + priv->channels[i].ipu = ipu; + priv->channels[i].data = &dmfcdata[i]; + } + + writel(0x0, priv->base + DMFC_WR_CHAN); + writel(0x0, priv->base + DMFC_DP_CHAN); + + /* + * We have a total bandwidth of clkrate * 4pixel divided + * into 8 slots. + */ + priv->bandwidth_per_slot = clk_get_rate(ipu_clk) / 8; + + dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n", + priv->bandwidth_per_slot / 1000000); + + writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF); + writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF); + writel(0x00000003, priv->base + DMFC_GENERAL1); + + return 0; +} + +void ipu_dmfc_exit(struct ipu_soc *ipu) +{ +} diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c new file mode 100644 index 000000000000..26aecaf9677f --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ +#include <linux/export.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/err.h> + +#include "imx-ipu-v3.h" +#include "ipu-prv.h" + +#define DP_SYNC 0 +#define DP_ASYNC0 0x60 +#define DP_ASYNC1 0xBC + +#define DP_COM_CONF 0x0 +#define DP_GRAPH_WIND_CTRL 0x0004 +#define DP_FG_POS 0x0008 +#define DP_CSC_A_0 0x0044 +#define DP_CSC_A_1 0x0048 +#define DP_CSC_A_2 0x004C +#define DP_CSC_A_3 0x0050 +#define DP_CSC_0 0x0054 +#define DP_CSC_1 0x0058 + +#define DP_COM_CONF_FG_EN (1 << 0) +#define DP_COM_CONF_GWSEL (1 << 1) +#define DP_COM_CONF_GWAM (1 << 2) +#define DP_COM_CONF_GWCKE (1 << 3) +#define DP_COM_CONF_CSC_DEF_MASK (3 << 8) +#define DP_COM_CONF_CSC_DEF_OFFSET 8 +#define DP_COM_CONF_CSC_DEF_FG (3 << 8) +#define DP_COM_CONF_CSC_DEF_BG (2 << 8) +#define DP_COM_CONF_CSC_DEF_BOTH (1 << 8) + +struct ipu_dp_priv; + +struct ipu_dp { + u32 flow; + bool in_use; + bool foreground; + enum ipu_color_space in_cs; +}; + +struct ipu_flow { + struct ipu_dp foreground; + struct ipu_dp background; + enum ipu_color_space out_cs; + void __iomem *base; + struct ipu_dp_priv *priv; +}; + +struct ipu_dp_priv { + struct ipu_soc *ipu; + struct device *dev; + void __iomem *base; + struct ipu_flow flow[3]; + struct mutex mutex; + int use_count; +}; + +static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1}; + +static inline struct ipu_flow *to_flow(struct ipu_dp *dp) +{ + if (dp->foreground) + return container_of(dp, struct ipu_flow, foreground); + else + return container_of(dp, struct ipu_flow, background); +} + +int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, + u8 alpha, bool bg_chan) +{ + struct ipu_flow *flow = to_flow(dp); + struct ipu_dp_priv *priv = flow->priv; + u32 reg; + + mutex_lock(&priv->mutex); + + reg = readl(flow->base + DP_COM_CONF); + if (bg_chan) + reg &= ~DP_COM_CONF_GWSEL; + else + reg |= DP_COM_CONF_GWSEL; + writel(reg, flow->base + DP_COM_CONF); + + if (enable) { + reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL; + writel(reg | ((u32) alpha << 24), + flow->base + DP_GRAPH_WIND_CTRL); + + reg = readl(flow->base + DP_COM_CONF); + writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); + } else { + reg = readl(flow->base + DP_COM_CONF); + writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); + } + + ipu_srm_dp_sync_update(priv->ipu); + + mutex_unlock(&priv->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha); + +int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos) +{ + struct ipu_flow *flow = to_flow(dp); + struct ipu_dp_priv *priv = flow->priv; + + writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS); + + ipu_srm_dp_sync_update(priv->ipu); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos); + +static void ipu_dp_csc_init(struct ipu_flow *flow, + enum ipu_color_space in, + enum ipu_color_space out, + u32 place) +{ + u32 reg; + + reg = readl(flow->base + DP_COM_CONF); + reg &= ~DP_COM_CONF_CSC_DEF_MASK; + + if (in == out) { + writel(reg, flow->base + DP_COM_CONF); + return; + } + + if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) { + writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0); + writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1); + writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2); + writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3); + writel(0x3d6 | (0x0000 << 16) | (2 << 30), + flow->base + DP_CSC_0); + writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30), + flow->base + DP_CSC_1); + } else { + writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0); + writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1); + writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2); + writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3); + writel(0x000 | (0x3e42 << 16) | (1 << 30), + flow->base + DP_CSC_0); + writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30), + flow->base + DP_CSC_1); + } + + reg |= place; + + writel(reg, flow->base + DP_COM_CONF); +} + +int ipu_dp_setup_channel(struct ipu_dp *dp, + enum ipu_color_space in, + enum ipu_color_space out) +{ + struct ipu_flow *flow = to_flow(dp); + struct ipu_dp_priv *priv = flow->priv; + + mutex_lock(&priv->mutex); + + dp->in_cs = in; + + if (!dp->foreground) + flow->out_cs = out; + + if (flow->foreground.in_cs == flow->background.in_cs) { + /* + * foreground and background are of same colorspace, put + * colorspace converter after combining unit. + */ + ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs, + DP_COM_CONF_CSC_DEF_BOTH); + } else { + if (flow->foreground.in_cs == flow->out_cs) + /* + * foreground identical to output, apply color + * conversion on background + */ + ipu_dp_csc_init(flow, flow->background.in_cs, + flow->out_cs, DP_COM_CONF_CSC_DEF_BG); + else + ipu_dp_csc_init(flow, flow->foreground.in_cs, + flow->out_cs, DP_COM_CONF_CSC_DEF_FG); + } + + ipu_srm_dp_sync_update(priv->ipu); + + mutex_unlock(&priv->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dp_setup_channel); + +int ipu_dp_enable_channel(struct ipu_dp *dp) +{ + struct ipu_flow *flow = to_flow(dp); + struct ipu_dp_priv *priv = flow->priv; + + mutex_lock(&priv->mutex); + + if (!priv->use_count) + ipu_module_enable(priv->ipu, IPU_CONF_DP_EN); + + priv->use_count++; + + if (dp->foreground) { + u32 reg; + + reg = readl(flow->base + DP_COM_CONF); + reg |= DP_COM_CONF_FG_EN; + writel(reg, flow->base + DP_COM_CONF); + + ipu_srm_dp_sync_update(priv->ipu); + } + + mutex_unlock(&priv->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_dp_enable_channel); + +void ipu_dp_disable_channel(struct ipu_dp *dp) +{ + struct ipu_flow *flow = to_flow(dp); + struct ipu_dp_priv *priv = flow->priv; + + mutex_lock(&priv->mutex); + + priv->use_count--; + + if (dp->foreground) { + u32 reg, csc; + + reg = readl(flow->base + DP_COM_CONF); + csc = reg & DP_COM_CONF_CSC_DEF_MASK; + if (csc == DP_COM_CONF_CSC_DEF_FG) + reg &= ~DP_COM_CONF_CSC_DEF_MASK; + + reg &= ~DP_COM_CONF_FG_EN; + writel(reg, flow->base + DP_COM_CONF); + + writel(0, flow->base + DP_FG_POS); + ipu_srm_dp_sync_update(priv->ipu); + } + + if (!priv->use_count) + ipu_module_disable(priv->ipu, IPU_CONF_DP_EN); + + if (priv->use_count < 0) + priv->use_count = 0; + + mutex_unlock(&priv->mutex); +} +EXPORT_SYMBOL_GPL(ipu_dp_disable_channel); + +struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow) +{ + struct ipu_dp_priv *priv = ipu->dp_priv; + struct ipu_dp *dp; + + if (flow > 5) + return ERR_PTR(-EINVAL); + + if (flow & 1) + dp = &priv->flow[flow >> 1].foreground; + else + dp = &priv->flow[flow >> 1].background; + + if (dp->in_use) + return ERR_PTR(-EBUSY); + + dp->in_use = true; + + return dp; +} +EXPORT_SYMBOL_GPL(ipu_dp_get); + +void ipu_dp_put(struct ipu_dp *dp) +{ + dp->in_use = false; +} +EXPORT_SYMBOL_GPL(ipu_dp_put); + +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) +{ + struct ipu_dp_priv *priv; + int i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + priv->dev = dev; + priv->ipu = ipu; + + ipu->dp_priv = priv; + + priv->base = devm_ioremap(dev, base, PAGE_SIZE); + if (!priv->base) { + kfree(priv); + return -ENOMEM; + } + + mutex_init(&priv->mutex); + + for (i = 0; i < 3; i++) { + priv->flow[i].foreground.foreground = 1; + priv->flow[i].base = priv->base + ipu_dp_flow_base[i]; + priv->flow[i].priv = priv; + } + + return 0; +} + +void ipu_dp_exit(struct ipu_soc *ipu) +{ +} diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h new file mode 100644 index 000000000000..551802863fd5 --- /dev/null +++ b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2010 Sascha Hauer <[email protected]> + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that 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. + */ +#ifndef __IPU_PRV_H__ +#define __IPU_PRV_H__ + +struct ipu_soc; + +#include <linux/types.h> +#include <linux/device.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include "imx-ipu-v3.h" + +#define IPUV3_CHANNEL_CSI0 0 +#define IPUV3_CHANNEL_CSI1 1 +#define IPUV3_CHANNEL_CSI2 2 +#define IPUV3_CHANNEL_CSI3 3 +#define IPUV3_CHANNEL_MEM_BG_SYNC 23 +#define IPUV3_CHANNEL_MEM_FG_SYNC 27 +#define IPUV3_CHANNEL_MEM_DC_SYNC 28 +#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA 31 +#define IPUV3_CHANNEL_MEM_DC_ASYNC 41 +#define IPUV3_CHANNEL_ROT_ENC_MEM 45 +#define IPUV3_CHANNEL_ROT_VF_MEM 46 +#define IPUV3_CHANNEL_ROT_PP_MEM 47 +#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT 48 +#define IPUV3_CHANNEL_ROT_VF_MEM_OUT 49 +#define IPUV3_CHANNEL_ROT_PP_MEM_OUT 50 +#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51 + +#define IPU_MCU_T_DEFAULT 8 +#define IPU_CM_IDMAC_REG_OFS 0x00008000 +#define IPU_CM_IC_REG_OFS 0x00020000 +#define IPU_CM_IRT_REG_OFS 0x00028000 +#define IPU_CM_CSI0_REG_OFS 0x00030000 +#define IPU_CM_CSI1_REG_OFS 0x00038000 +#define IPU_CM_SMFC_REG_OFS 0x00050000 +#define IPU_CM_DC_REG_OFS 0x00058000 +#define IPU_CM_DMFC_REG_OFS 0x00060000 + +/* Register addresses */ +/* IPU Common registers */ +#define IPU_CM_REG(offset) (offset) + +#define IPU_CONF IPU_CM_REG(0) + +#define IPU_SRM_PRI1 IPU_CM_REG(0x00a0) +#define IPU_SRM_PRI2 IPU_CM_REG(0x00a4) +#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00a8) +#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00ac) +#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00b0) +#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00b4) +#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00b8) +#define IPU_SKIP IPU_CM_REG(0x00bc) +#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00c0) +#define IPU_DISP_GEN IPU_CM_REG(0x00c4) +#define IPU_DISP_ALT1 IPU_CM_REG(0x00c8) +#define IPU_DISP_ALT2 IPU_CM_REG(0x00cc) +#define IPU_DISP_ALT3 IPU_CM_REG(0x00d0) +#define IPU_DISP_ALT4 IPU_CM_REG(0x00d4) +#define IPU_SNOOP IPU_CM_REG(0x00d8) +#define IPU_MEM_RST IPU_CM_REG(0x00dc) +#define IPU_PM IPU_CM_REG(0x00e0) +#define IPU_GPR IPU_CM_REG(0x00e4) +#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32)) +#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32)) +#define IPU_CHA_CUR_BUF(ch) IPU_CM_REG(0x023C + 4 * ((ch) / 32)) +#define IPU_ALT_CUR_BUF0 IPU_CM_REG(0x0244) +#define IPU_ALT_CUR_BUF1 IPU_CM_REG(0x0248) +#define IPU_SRM_STAT IPU_CM_REG(0x024C) +#define IPU_PROC_TASK_STAT IPU_CM_REG(0x0250) +#define IPU_DISP_TASK_STAT IPU_CM_REG(0x0254) +#define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0268 + 4 * ((ch) / 32)) +#define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0270 + 4 * ((ch) / 32)) +#define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0278 + 4 * ((ch) / 32)) +#define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0280 + 4 * ((ch) / 32)) + +#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) +#define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) + +#define IPU_DI0_COUNTER_RELEASE (1 << 24) +#define IPU_DI1_COUNTER_RELEASE (1 << 25) + +#define IPU_IDMAC_REG(offset) (offset) + +#define IDMAC_CONF IPU_IDMAC_REG(0x0000) +#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32)) +#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000c) +#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010) +#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32)) +#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32)) +#define IDMAC_CH_LOCK_EN_1 IPU_IDMAC_REG(0x0024) +#define IDMAC_CH_LOCK_EN_2 IPU_IDMAC_REG(0x0028) +#define IDMAC_SUB_ADDR_0 IPU_IDMAC_REG(0x002c) +#define IDMAC_SUB_ADDR_1 IPU_IDMAC_REG(0x0030) +#define IDMAC_SUB_ADDR_2 IPU_IDMAC_REG(0x0034) +#define IDMAC_BAND_EN(ch) IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32)) +#define IDMAC_CHA_BUSY(ch) IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32)) + +#define IPU_NUM_IRQS (32 * 5) + +enum ipu_modules { + IPU_CONF_CSI0_EN = (1 << 0), + IPU_CONF_CSI1_EN = (1 << 1), + IPU_CONF_IC_EN = (1 << 2), + IPU_CONF_ROT_EN = (1 << 3), + IPU_CONF_ISP_EN = (1 << 4), + IPU_CONF_DP_EN = (1 << 5), + IPU_CONF_DI0_EN = (1 << 6), + IPU_CONF_DI1_EN = (1 << 7), + IPU_CONF_SMFC_EN = (1 << 8), + IPU_CONF_DC_EN = (1 << 9), + IPU_CONF_DMFC_EN = (1 << 10), + + IPU_CONF_VDI_EN = (1 << 12), + + IPU_CONF_IDMAC_DIS = (1 << 22), + + IPU_CONF_IC_DMFC_SEL = (1 << 25), + IPU_CONF_IC_DMFC_SYNC = (1 << 26), + IPU_CONF_VDI_DMFC_SYNC = (1 << 27), + + IPU_CONF_CSI0_DATA_SOURCE = (1 << 28), + IPU_CONF_CSI1_DATA_SOURCE = (1 << 29), + IPU_CONF_IC_INPUT = (1 << 30), + IPU_CONF_CSI_SEL = (1 << 31), +}; + +struct ipuv3_channel { + unsigned int num; + + bool enabled; + bool busy; + + struct ipu_soc *ipu; +}; + +struct ipu_dc_priv; +struct ipu_dmfc_priv; +struct ipu_di; +struct ipu_devtype; + +struct ipu_soc { + struct device *dev; + const struct ipu_devtype *devtype; + enum ipuv3_type ipu_type; + spinlock_t lock; + struct mutex channel_lock; + + void __iomem *cm_reg; + void __iomem *idmac_reg; + struct ipu_ch_param __iomem *cpmem_base; + + int usecount; + + struct clk *clk; + + struct ipuv3_channel channel[64]; + + int irq_start; + int irq_sync; + int irq_err; + + struct ipu_dc_priv *dc_priv; + struct ipu_dp_priv *dp_priv; + struct ipu_dmfc_priv *dmfc_priv; + struct ipu_di *di_priv[2]; +}; + +void ipu_srm_dp_sync_update(struct ipu_soc *ipu); + +int ipu_module_enable(struct ipu_soc *ipu, u32 mask); +int ipu_module_disable(struct ipu_soc *ipu, u32 mask); + +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id, + unsigned long base, u32 module, struct clk *ipu_clk); +void ipu_di_exit(struct ipu_soc *ipu, int id); + +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, + struct clk *ipu_clk); +void ipu_dmfc_exit(struct ipu_soc *ipu); + +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); +void ipu_dp_exit(struct ipu_soc *ipu); + +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base, + unsigned long template_base); +void ipu_dc_exit(struct ipu_soc *ipu); + +int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); +void ipu_cpmem_exit(struct ipu_soc *ipu); + +#endif /* __IPU_PRV_H__ */ diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c new file mode 100644 index 000000000000..78d3edac75c1 --- /dev/null +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -0,0 +1,579 @@ +/* + * i.MX IPUv3 Graphics driver + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that 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 Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include <linux/module.h> +#include <linux/export.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> +#include <linux/fb.h> +#include <linux/clk.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "ipu-v3/imx-ipu-v3.h" +#include "imx-drm.h" + +#define DRIVER_DESC "i.MX IPUv3 Graphics" + +struct ipu_framebuffer { + struct drm_framebuffer base; + void *virt; + dma_addr_t phys; + size_t len; +}; + +struct ipu_crtc { + struct drm_fb_helper fb_helper; + struct ipu_framebuffer ifb; + int num_crtcs; + struct device *dev; + struct drm_crtc base; + struct imx_drm_crtc *imx_crtc; + struct ipuv3_channel *ipu_ch; + struct ipu_dc *dc; + struct ipu_dp *dp; + struct dmfc_channel *dmfc; + struct ipu_di *di; + int enabled; + struct ipu_priv *ipu_priv; + struct drm_pending_vblank_event *page_flip_event; + struct drm_framebuffer *newfb; + int irq; + u32 interface_pix_fmt; + unsigned long di_clkflags; +}; + +#define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) + +static int calc_vref(struct drm_display_mode *mode) +{ + unsigned long htotal, vtotal; + + htotal = mode->htotal; + vtotal = mode->vtotal; + + if (!htotal || !vtotal) + return 60; + + return mode->clock * 1000 / vtotal / htotal; +} + +static int calc_bandwidth(struct drm_display_mode *mode, unsigned int vref) +{ + return mode->hdisplay * mode->vdisplay * vref; +} + +static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) +{ + if (ipu_crtc->enabled) + return; + + ipu_di_enable(ipu_crtc->di); + ipu_dmfc_enable_channel(ipu_crtc->dmfc); + ipu_idmac_enable_channel(ipu_crtc->ipu_ch); + ipu_dc_enable_channel(ipu_crtc->dc); + if (ipu_crtc->dp) + ipu_dp_enable_channel(ipu_crtc->dp); + + ipu_crtc->enabled = 1; +} + +static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) +{ + if (!ipu_crtc->enabled) + return; + + if (ipu_crtc->dp) + ipu_dp_disable_channel(ipu_crtc->dp); + ipu_dc_disable_channel(ipu_crtc->dc); + ipu_idmac_disable_channel(ipu_crtc->ipu_ch); + ipu_dmfc_disable_channel(ipu_crtc->dmfc); + ipu_di_disable(ipu_crtc->di); + + ipu_crtc->enabled = 0; +} + +static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + dev_info(ipu_crtc->dev, "%s mode: %d\n", __func__, mode); + + switch (mode) { + case DRM_MODE_DPMS_ON: + ipu_fb_enable(ipu_crtc); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + ipu_fb_disable(ipu_crtc); + break; + } +} + +static int ipu_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + int ret; + + if (ipu_crtc->newfb) + return -EBUSY; + + ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc); + if (ret) { + dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n"); + list_del(&event->base.link); + + return ret; + } + + ipu_crtc->newfb = fb; + ipu_crtc->page_flip_event = event; + + return 0; +} + +static const struct drm_crtc_funcs ipu_crtc_funcs = { + .set_config = drm_crtc_helper_set_config, + .destroy = drm_crtc_cleanup, + .page_flip = ipu_page_flip, +}; + +static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + struct drm_gem_cma_object *cma_obj; + struct drm_framebuffer *fb = crtc->fb; + unsigned long phys; + + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + if (!cma_obj) { + DRM_LOG_KMS("entry is null.\n"); + return -EFAULT; + } + + phys = cma_obj->paddr; + phys += x * (fb->bits_per_pixel >> 3); + phys += y * fb->pitches[0]; + + dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); + dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); + + ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]); + ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch), + 0, phys); + + return 0; +} + +static int ipu_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *orig_mode, + struct drm_display_mode *mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + struct drm_framebuffer *fb = ipu_crtc->base.fb; + int ret; + struct ipu_di_signal_cfg sig_cfg = {}; + u32 out_pixel_fmt; + struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch); + int bpp; + u32 v4l2_fmt; + + dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, + mode->hdisplay); + dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, + mode->vdisplay); + + ipu_ch_param_zero(cpmem); + + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + v4l2_fmt = V4L2_PIX_FMT_RGB32; + bpp = 32; + break; + case DRM_FORMAT_RGB565: + v4l2_fmt = V4L2_PIX_FMT_RGB565; + bpp = 16; + break; + case DRM_FORMAT_RGB888: + v4l2_fmt = V4L2_PIX_FMT_RGB24; + bpp = 24; + break; + default: + dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n", + fb->pixel_format); + return -EINVAL; + } + + out_pixel_fmt = ipu_crtc->interface_pix_fmt; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + sig_cfg.interlaced = 1; + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + sig_cfg.Hsync_pol = 1; + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + sig_cfg.Vsync_pol = 1; + + sig_cfg.enable_pol = 1; + sig_cfg.clk_pol = 0; + sig_cfg.width = mode->hdisplay; + sig_cfg.height = mode->vdisplay; + sig_cfg.pixel_fmt = out_pixel_fmt; + sig_cfg.h_start_width = mode->htotal - mode->hsync_end; + sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start; + sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay; + + sig_cfg.v_start_width = mode->vtotal - mode->vsync_end; + sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start; + sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay; + sig_cfg.pixelclock = mode->clock * 1000; + sig_cfg.clkflags = ipu_crtc->di_clkflags; + + sig_cfg.v_to_h_sync = 0; + + if (ipu_crtc->dp) { + ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB, + IPUV3_COLORSPACE_RGB); + if (ret) { + dev_err(ipu_crtc->dev, + "initializing display processor failed with %d\n", + ret); + return ret; + } + ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1); + } + + ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, + out_pixel_fmt, mode->hdisplay); + if (ret) { + dev_err(ipu_crtc->dev, + "initializing display controller failed with %d\n", + ret); + return ret; + } + + ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); + if (ret) { + dev_err(ipu_crtc->dev, + "initializing panel failed with %d\n", ret); + return ret; + } + + ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay); + ipu_cpmem_set_fmt(cpmem, v4l2_fmt); + ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch); + + ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay); + if (ret) { + dev_err(ipu_crtc->dev, + "initializing dmfc channel failed with %d\n", + ret); + return ret; + } + + ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc, + calc_bandwidth(mode, calc_vref(mode)), 64); + if (ret) { + dev_err(ipu_crtc->dev, + "allocating dmfc bandwidth failed with %d\n", + ret); + return ret; + } + + ipu_drm_set_base(crtc, x, y); + + return 0; +} + +static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) +{ + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + struct drm_device *drm = ipu_crtc->base.dev; + + spin_lock_irqsave(&drm->event_lock, flags); + + e = ipu_crtc->page_flip_event; + if (!e) { + spin_unlock_irqrestore(&drm->event_lock, flags); + return; + } + + do_gettimeofday(&now); + e->event.sequence = 0; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + ipu_crtc->page_flip_event = NULL; + + imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); + + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + + wake_up_interruptible(&e->base.file_priv->event_wait); + + spin_unlock_irqrestore(&drm->event_lock, flags); +} + +static irqreturn_t ipu_irq_handler(int irq, void *dev_id) +{ + struct ipu_crtc *ipu_crtc = dev_id; + + imx_drm_handle_vblank(ipu_crtc->imx_crtc); + + if (ipu_crtc->newfb) { + ipu_crtc->base.fb = ipu_crtc->newfb; + ipu_crtc->newfb = NULL; + ipu_drm_set_base(&ipu_crtc->base, 0, 0); + ipu_crtc_handle_pageflip(ipu_crtc); + } + + return IRQ_HANDLED; +} + +static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void ipu_crtc_prepare(struct drm_crtc *crtc) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + ipu_fb_disable(ipu_crtc); +} + +static void ipu_crtc_commit(struct drm_crtc *crtc) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + ipu_fb_enable(ipu_crtc); +} + +static void ipu_crtc_load_lut(struct drm_crtc *crtc) +{ +} + +static struct drm_crtc_helper_funcs ipu_helper_funcs = { + .dpms = ipu_crtc_dpms, + .mode_fixup = ipu_crtc_mode_fixup, + .mode_set = ipu_crtc_mode_set, + .prepare = ipu_crtc_prepare, + .commit = ipu_crtc_commit, + .load_lut = ipu_crtc_load_lut, +}; + +static int ipu_enable_vblank(struct drm_crtc *crtc) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + enable_irq(ipu_crtc->irq); + + return 0; +} + +static void ipu_disable_vblank(struct drm_crtc *crtc) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + disable_irq(ipu_crtc->irq); +} + +static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, + u32 pixfmt) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + ipu_crtc->interface_pix_fmt = pixfmt; + + switch (encoder_type) { + case DRM_MODE_ENCODER_LVDS: + ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC | + IPU_DI_CLKMODE_EXT; + break; + case DRM_MODE_ENCODER_NONE: + ipu_crtc->di_clkflags = 0; + break; + } + + return 0; +} + +static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { + .enable_vblank = ipu_enable_vblank, + .disable_vblank = ipu_disable_vblank, + .set_interface_pix_fmt = ipu_set_interface_pix_fmt, + .crtc_funcs = &ipu_crtc_funcs, + .crtc_helper_funcs = &ipu_helper_funcs, +}; + +static void ipu_put_resources(struct ipu_crtc *ipu_crtc) +{ + if (!IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) + ipu_idmac_put(ipu_crtc->ipu_ch); + if (!IS_ERR_OR_NULL(ipu_crtc->dmfc)) + ipu_dmfc_put(ipu_crtc->dmfc); + if (!IS_ERR_OR_NULL(ipu_crtc->dp)) + ipu_dp_put(ipu_crtc->dp); + if (!IS_ERR_OR_NULL(ipu_crtc->di)) + ipu_di_put(ipu_crtc->di); +} + +static int ipu_get_resources(struct ipu_crtc *ipu_crtc, + struct ipu_client_platformdata *pdata) +{ + struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); + int ret; + + ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); + if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) { + ret = PTR_ERR(ipu_crtc->ipu_ch); + goto err_out; + } + + ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); + if (IS_ERR(ipu_crtc->dc)) { + ret = PTR_ERR(ipu_crtc->dc); + goto err_out; + } + + ipu_crtc->dmfc = ipu_dmfc_get(ipu, pdata->dma[0]); + if (IS_ERR(ipu_crtc->dmfc)) { + ret = PTR_ERR(ipu_crtc->dmfc); + goto err_out; + } + + if (pdata->dp >= 0) { + ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); + if (IS_ERR(ipu_crtc->dp)) { + ret = PTR_ERR(ipu_crtc->ipu_ch); + goto err_out; + } + } + + ipu_crtc->di = ipu_di_get(ipu, pdata->di); + if (IS_ERR(ipu_crtc->di)) { + ret = PTR_ERR(ipu_crtc->di); + goto err_out; + } + + ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch, + IPU_IRQ_EOF); + ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, + "imx_drm", ipu_crtc); + if (ret < 0) { + dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); + goto err_out; + } + + disable_irq(ipu_crtc->irq); + + return 0; +err_out: + ipu_put_resources(ipu_crtc); + + return ret; +} + +static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, + struct ipu_client_platformdata *pdata) +{ + int ret; + + ret = ipu_get_resources(ipu_crtc, pdata); + if (ret) { + dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", + ret); + return ret; + } + + ret = imx_drm_add_crtc(&ipu_crtc->base, + &ipu_crtc->imx_crtc, + &ipu_crtc_helper_funcs, THIS_MODULE, + ipu_crtc->dev->parent->of_node, pdata->di); + if (ret) { + dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); + goto err_put_resources; + } + + return 0; + +err_put_resources: + ipu_put_resources(ipu_crtc); + + return ret; +} + +static int __devinit ipu_drm_probe(struct platform_device *pdev) +{ + struct ipu_client_platformdata *pdata = pdev->dev.platform_data; + struct ipu_crtc *ipu_crtc; + int ret; + + if (!pdata) + return -EINVAL; + + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL); + if (!ipu_crtc) + return -ENOMEM; + + ipu_crtc->dev = &pdev->dev; + + ret = ipu_crtc_init(ipu_crtc, pdata); + + platform_set_drvdata(pdev, ipu_crtc); + + return 0; +} + +static int __devexit ipu_drm_remove(struct platform_device *pdev) +{ + struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev); + + imx_drm_remove_crtc(ipu_crtc->imx_crtc); + + ipu_put_resources(ipu_crtc); + + return 0; +} + +static struct platform_driver ipu_drm_driver = { + .driver = { + .name = "imx-ipuv3-crtc", + }, + .probe = ipu_drm_probe, + .remove = __devexit_p(ipu_drm_remove), +}; +module_platform_driver(ipu_drm_driver); + +MODULE_AUTHOR("Sascha Hauer <[email protected]>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c new file mode 100644 index 000000000000..9b51d732eefa --- /dev/null +++ b/drivers/staging/imx-drm/parallel-display.c @@ -0,0 +1,261 @@ +/* + * i.MX drm driver - parallel display implementation + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that 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 Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> +#include <linux/videodev2.h> + +#include "imx-drm.h" + +#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) +#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder) + +struct imx_parallel_display { + struct drm_connector connector; + struct imx_drm_connector *imx_drm_connector; + struct drm_encoder encoder; + struct imx_drm_encoder *imx_drm_encoder; + struct device *dev; + void *edid; + int edid_len; + u32 interface_pix_fmt; + int mode_valid; + struct drm_display_mode mode; +}; + +static enum drm_connector_status imx_pd_connector_detect( + struct drm_connector *connector, bool force) +{ + return connector_status_connected; +} + +static void imx_pd_connector_destroy(struct drm_connector *connector) +{ + /* do not free here */ +} + +static int imx_pd_connector_get_modes(struct drm_connector *connector) +{ + struct imx_parallel_display *imxpd = con_to_imxpd(connector); + int num_modes = 0; + + if (imxpd->edid) { + drm_mode_connector_update_edid_property(connector, imxpd->edid); + num_modes = drm_add_edid_modes(connector, imxpd->edid); + } + + if (imxpd->mode_valid) { + struct drm_display_mode *mode = drm_mode_create(connector->dev); + drm_mode_copy(mode, &imxpd->mode); + mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + drm_mode_probed_add(connector, mode); + num_modes++; + } + + return num_modes; +} + +static int imx_pd_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return 0; +} + +static struct drm_encoder *imx_pd_connector_best_encoder( + struct drm_connector *connector) +{ + struct imx_parallel_display *imxpd = con_to_imxpd(connector); + + return &imxpd->encoder; +} + +static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) +{ +} + +static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void imx_pd_encoder_prepare(struct drm_encoder *encoder) +{ + struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); + + imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE, + imxpd->interface_pix_fmt); +} + +static void imx_pd_encoder_commit(struct drm_encoder *encoder) +{ +} + +static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ +} + +static void imx_pd_encoder_disable(struct drm_encoder *encoder) +{ +} + +static void imx_pd_encoder_destroy(struct drm_encoder *encoder) +{ + /* do not free here */ +} + +static struct drm_connector_funcs imx_pd_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = imx_pd_connector_detect, + .destroy = imx_pd_connector_destroy, +}; + +static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { + .get_modes = imx_pd_connector_get_modes, + .best_encoder = imx_pd_connector_best_encoder, + .mode_valid = imx_pd_connector_mode_valid, +}; + +static struct drm_encoder_funcs imx_pd_encoder_funcs = { + .destroy = imx_pd_encoder_destroy, +}; + +static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { + .dpms = imx_pd_encoder_dpms, + .mode_fixup = imx_pd_encoder_mode_fixup, + .prepare = imx_pd_encoder_prepare, + .commit = imx_pd_encoder_commit, + .mode_set = imx_pd_encoder_mode_set, + .disable = imx_pd_encoder_disable, +}; + +static int imx_pd_register(struct imx_parallel_display *imxpd) +{ + int ret; + + drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); + + imxpd->connector.funcs = &imx_pd_connector_funcs; + imxpd->encoder.funcs = &imx_pd_encoder_funcs; + + imxpd->encoder.encoder_type = DRM_MODE_ENCODER_NONE; + imxpd->connector.connector_type = DRM_MODE_CONNECTOR_VGA; + + drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); + ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, + THIS_MODULE); + if (ret) { + dev_err(imxpd->dev, "adding encoder failed with %d\n", ret); + return ret; + } + + drm_connector_helper_add(&imxpd->connector, + &imx_pd_connector_helper_funcs); + + ret = imx_drm_add_connector(&imxpd->connector, + &imxpd->imx_drm_connector, THIS_MODULE); + if (ret) { + imx_drm_remove_encoder(imxpd->imx_drm_encoder); + dev_err(imxpd->dev, "adding connector failed with %d\n", ret); + return ret; + } + + imxpd->connector.encoder = &imxpd->encoder; + + return 0; +} + +static int __devinit imx_pd_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const u8 *edidp; + struct imx_parallel_display *imxpd; + int ret; + const char *fmt; + + imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL); + if (!imxpd) + return -ENOMEM; + + edidp = of_get_property(np, "edid", &imxpd->edid_len); + if (edidp) + imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); + + ret = of_property_read_string(np, "interface-pix-fmt", &fmt); + if (!ret) { + if (!strcmp(fmt, "rgb24")) + imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB24; + else if (!strcmp(fmt, "rgb565")) + imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565; + } + + imxpd->dev = &pdev->dev; + + ret = imx_pd_register(imxpd); + if (ret) + return ret; + + ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np); + + platform_set_drvdata(pdev, imxpd); + + return 0; +} + +static int __devexit imx_pd_remove(struct platform_device *pdev) +{ + struct imx_parallel_display *imxpd = platform_get_drvdata(pdev); + struct drm_connector *connector = &imxpd->connector; + struct drm_encoder *encoder = &imxpd->encoder; + + drm_mode_connector_detach_encoder(connector, encoder); + + imx_drm_remove_connector(imxpd->imx_drm_connector); + imx_drm_remove_encoder(imxpd->imx_drm_encoder); + + return 0; +} + +static const struct of_device_id imx_pd_dt_ids[] = { + { .compatible = "fsl,imx-parallel-display", }, + { /* sentinel */ } +}; + +static struct platform_driver imx_pd_driver = { + .probe = imx_pd_probe, + .remove = __devexit_p(imx_pd_remove), + .driver = { + .of_match_table = imx_pd_dt_ids, + .name = "imx-parallel-display", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(imx_pd_driver); + +MODULE_DESCRIPTION("i.MX parallel display driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c index ff93c15d349b..368a2e19b2d4 100644 --- a/drivers/staging/omap-thermal/omap-bandgap.c +++ b/drivers/staging/omap-thermal/omap-bandgap.c @@ -157,7 +157,7 @@ static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i, high = ts_data->adc_end_val - ts_data->adc_start_val; mid = (high + low) / 2; - if (temp < bg_ptr->conv_table[high] || temp > bg_ptr->conv_table[high]) + if (temp < bg_ptr->conv_table[low] || temp > bg_ptr->conv_table[high]) return -EINVAL; while (low < high) { diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 758ce0a8d82e..64913aeb0bac 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -104,10 +104,10 @@ ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count, if (pd) oz_pd_get(pd); spin_unlock_bh(&g_cdev.lock); - if (pd == 0) + if (pd == NULL) return -1; ctx = oz_cdev_claim_ctx(pd); - if (ctx == 0) + if (ctx == NULL) goto out2; n = ctx->rd_in - ctx->rd_out; if (n < 0) @@ -157,11 +157,11 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count, if (pd) oz_pd_get(pd); spin_unlock_bh(&g_cdev.lock); - if (pd == 0) + if (pd == NULL) return -1; eb = &pd->elt_buff; ei = oz_elt_info_alloc(eb); - if (ei == 0) { + if (ei == NULL) { count = 0; goto out; } @@ -410,7 +410,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume) return 0; } ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC); - if (ctx == 0) + if (ctx == NULL) return -ENOMEM; atomic_set(&ctx->ref_count, 1); ctx->tx_seq_num = 1; @@ -424,7 +424,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume) spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]); } spin_lock(&g_cdev.lock); - if ((g_cdev.active_pd == 0) && + if ((g_cdev.active_pd == NULL) && (memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) { oz_pd_get(pd); g_cdev.active_pd = pd; @@ -477,7 +477,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) int ix; ctx = oz_cdev_claim_ctx(pd); - if (ctx == 0) { + if (ctx == NULL) { oz_trace("Cannot claim serial context.\n"); return; } diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index f7426b44ee08..6e9f7090c451 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -1197,7 +1197,7 @@ static inline int handle_lcd_special_code(void) break; } - /* Check wether one flag was changed */ + /* Check whether one flag was changed */ if (oldflags != lcd_flags) { /* check whether one of B,C,D flags were changed */ if ((oldflags ^ lcd_flags) & @@ -1212,7 +1212,7 @@ static inline int handle_lcd_special_code(void) lcd_write_cmd(0x30 | ((lcd_flags & LCD_FLAG_F) ? 4 : 0) | ((lcd_flags & LCD_FLAG_N) ? 8 : 0)); - /* check wether L flag was changed */ + /* check whether L flag was changed */ else if ((oldflags ^ lcd_flags) & (LCD_FLAG_L)) { if (lcd_flags & (LCD_FLAG_L)) lcd_backlight(1); diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 99e907d46224..4feecec8609c 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -267,7 +267,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) else ieee->seq_ctrl[0]++; - /* check wether the managed packet queued greater than 5 */ + /* check whether the managed packet queued greater than 5 */ if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) || (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) || (ieee->queue_stop)) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 9f625bc1b4a1..7a0707810fd0 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -271,7 +271,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee else ieee->seq_ctrl[0]++; - /* check wether the managed packet queued greater than 5 */ + /* check whether the managed packet queued greater than 5 */ if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ (ieee->queue_stop) ) { diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index 213829ec7df9..afe9c2e763d7 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -352,12 +352,8 @@ static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - dev_info(&dev->pci->dev, "Ready to suspend\n"); - - if (!dev) { - dev_err(&dev->pci->dev, "Invalid memory\n"); + if (!dev) return 0; - } /* lock the device pointers */ mutex_lock(&(dev->dev_mutex)); @@ -391,12 +387,8 @@ static int rtsx_resume(struct pci_dev *pci) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - dev_info(&dev->pci->dev, "Ready to resume\n"); - - if (!dev) { - dev_err(&dev->pci->dev, "Invalid memory\n"); + if (!dev) return 0; - } chip = dev->chip; @@ -441,12 +433,8 @@ static void rtsx_shutdown(struct pci_dev *pci) struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); struct rtsx_chip *chip; - dev_info(&dev->pci->dev, "Ready to shutdown\n"); - - if (!dev) { - dev_err(&dev->pci->dev, "Invalid memory\n"); + if (!dev) return; - } chip = dev->chip; diff --git a/drivers/staging/sbe-2t3e3/2t3e3.h b/drivers/staging/sbe-2t3e3/2t3e3.h index 383f2cfc1ad2..ccad049c1122 100644 --- a/drivers/staging/sbe-2t3e3/2t3e3.h +++ b/drivers/staging/sbe-2t3e3/2t3e3.h @@ -789,7 +789,6 @@ void dc_restart(struct channel *); void dc_receiver_onoff(struct channel *, u32); void dc_transmitter_onoff(struct channel *, u32); void dc_set_loopback(struct channel *, u32); -u32 dc_init_descriptor_list(struct channel *); void dc_clear_descriptor_list(struct channel *); void dc_drop_descriptor_list(struct channel *); void dc_set_output_port(struct channel *); diff --git a/drivers/staging/sbe-2t3e3/dc.c b/drivers/staging/sbe-2t3e3/dc.c index 9e81d9036a33..daadd6ea4978 100644 --- a/drivers/staging/sbe-2t3e3/dc.c +++ b/drivers/staging/sbe-2t3e3/dc.c @@ -17,6 +17,8 @@ #include "2t3e3.h" #include "ctrl.h" +static int dc_init_descriptor_list(struct channel *sc); + void dc_init(struct channel *sc) { u32 val; @@ -307,7 +309,7 @@ void dc_set_loopback(struct channel *sc, u32 mode) SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); } -u32 dc_init_descriptor_list(struct channel *sc) +static int dc_init_descriptor_list(struct channel *sc) { u32 i, j; struct sk_buff *m; @@ -317,7 +319,7 @@ u32 dc_init_descriptor_list(struct channel *sc) sizeof(t3e3_rx_desc_t), GFP_KERNEL); if (sc->ether.rx_ring == NULL) { dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); - return ENOMEM; + return -ENOMEM; } if (sc->ether.tx_ring == NULL) @@ -327,7 +329,7 @@ u32 dc_init_descriptor_list(struct channel *sc) kfree(sc->ether.rx_ring); sc->ether.rx_ring = NULL; dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); - return ENOMEM; + return -ENOMEM; } @@ -351,7 +353,7 @@ u32 dc_init_descriptor_list(struct channel *sc) sc->ether.tx_ring = NULL; dev_err(&sc->pdev->dev, "SBE 2T3E3: token_alloc err:" " no buffer space for RX ring\n"); - return ENOBUFS; + return -ENOBUFS; } sc->ether.rx_data[i] = m; } diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c index cd778b3a02b2..8adb17816ad9 100644 --- a/drivers/staging/sbe-2t3e3/module.c +++ b/drivers/staging/sbe-2t3e3/module.c @@ -67,6 +67,7 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * dev = alloc_hdlcdev(channel); if (!dev) { printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n"); + err = -ENOMEM; goto free_regions; } @@ -82,8 +83,9 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * else channel->h.slot = 0; - if (setup_device(dev, channel)) - goto free_regions; + err = setup_device(dev, channel); + if (err) + goto free_dev; pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */ pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF); @@ -92,14 +94,19 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev * pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command); t3e3_init(channel); - if (request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev)) { + err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev); + if (err) { printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq); - goto free_regions; + goto unregister_dev; } pci_set_drvdata(pdev, channel); return 0; +unregister_dev: + unregister_hdlc_device(dev); +free_dev: + free_netdev(dev); free_regions: pci_release_regions(pdev); disable: diff --git a/drivers/staging/silicom/Kconfig b/drivers/staging/silicom/Kconfig index cb07a0da0f63..eda2e7d73645 100644 --- a/drivers/staging/silicom/Kconfig +++ b/drivers/staging/silicom/Kconfig @@ -19,7 +19,7 @@ if NET_VENDOR_SILICOM config SBYPASS tristate "Silicom BypassCTL library support" - depends on PCI + depends on PCI && NET depends on m ---help--- If you have a network (Ethernet) controller of this type, say Y @@ -29,7 +29,7 @@ config SBYPASS config BPCTL tristate "Silicom BypassCTL net support" - depends on PCI + depends on PCI && NET depends on m select SBYPASS select NET_CORE diff --git a/drivers/staging/silicom/bp_mod.c b/drivers/staging/silicom/bp_mod.c index d1cf246ee7bb..3cfd0516adfa 100644 --- a/drivers/staging/silicom/bp_mod.c +++ b/drivers/staging/silicom/bp_mod.c @@ -127,16 +127,12 @@ typedef struct _bpctl_dev { int bp_10g9; int bp_i80; int bp_540; - -// selftest stanza int (*hard_start_xmit_save) (struct sk_buff *skb, struct net_device *dev); const struct net_device_ops *old_ops; struct net_device_ops new_ops; int bp_self_test_flag; char *bp_tx_data; -// end selftest stanza -// struct bypass_pfs_sd bypass_pfs_set; } bpctl_dev_t; @@ -168,14 +164,13 @@ static int bp_device_event(struct notifier_block *unused, struct net_device *dev = ptr; static bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; int dev_num = 0, ret = 0, ret_d = 0, time_left = 0; - //printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); - //return NOTIFY_DONE; + /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */ + /* return NOTIFY_DONE; */ if (!dev) return NOTIFY_DONE; if (event == NETDEV_REGISTER) { { struct ethtool_drvinfo drvinfo; - // char *str=NULL; char cbuf[32]; char *buf = NULL; char res[10]; @@ -198,13 +193,6 @@ static int bp_device_event(struct notifier_block *unused, memcpy(&cbuf, drvinfo.bus_info, 32); buf = &cbuf[0]; - // while(*buf++){ - - /*if(*buf==':'){ - buf++; - break; - } */ - //} while (*buf++ != ':') ; for (i = 0; i < 10; i++, buf++) { if (*buf == ':') @@ -245,7 +233,6 @@ static int bp_device_event(struct notifier_block *unused, } if (event == NETDEV_UNREGISTER) { int idx_dev = 0; - //if_scan(); for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); idx_dev++) { @@ -263,7 +250,6 @@ static int bp_device_event(struct notifier_block *unused, } if (event == NETDEV_CHANGENAME) { int idx_dev = 0; - //if_scan(); for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); idx_dev++) { @@ -281,7 +267,6 @@ static int bp_device_event(struct notifier_block *unused, return NOTIFY_DONE; } - //return NOTIFY_DONE; switch (event) { @@ -289,7 +274,6 @@ static int bp_device_event(struct notifier_block *unused, if (netif_carrier_ok(dev)) return NOTIFY_DONE; - //if_scan(); if (((dev_num = get_dev_idx(dev->ifindex)) == -1) || (!(pbpctl_dev = &bpctl_dev_arr[dev_num]))) return NOTIFY_DONE; @@ -441,12 +425,10 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev, BPCTLI_CTRL_EXT_MCLK_DATA)); else { -/* To start management : MCLK 1, MDIO 1, output*/ - //writel((0x2|0x8), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; + /* To start management : MCLK 1, MDIO 1, output*/ BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext | BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl | BP10G_MDIO_DATA | BP10G_MDIO_DIR)); } @@ -513,12 +495,10 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev, (BPCTLI_CTRL_EXT_MCLK_DATA))); else { - //writel((0x2), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MDIO_DATA_OUT) & ~(BP10G_MCLK_DATA_OUT))); - // BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl |BP10G_MDIO_DIR|BP10G_MDIO_DATA)); } usec_delay(PULSE_TIME); @@ -584,12 +564,10 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev, (BPCTLI_CTRL_EXT_MDIO_DATA))); else { - // writel((0x8), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MCLK_DATA_OUT) & ~BP10G_MDIO_DATA_OUT)); - // BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } usec_delay(PULSE_TIME); @@ -652,12 +630,10 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev, BPCTLI_CTRL_EXT_MDIO_DATA))); else { - //writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } usec_delay(PULSE_TIME); @@ -684,7 +660,6 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); } - //ctrl_ext=BP10G_READ_REG(pbpctl_dev,EODSDP); while (i--) { if (pbpctl_dev->bp_10g9) { @@ -735,10 +710,8 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, BPCTLI_CTRL_EXT_MCLK_DATA))); else { - // writel(( 0/*0x1*/), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MDIO_DATA_OUT) & ~BP10G_MCLK_DATA_OUT)); /* ? */ - // printk("0x28=0x%x\n",BP10G_READ_REG(pbpctl_dev,EODSDP);); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl &~BP10G_MDIO_DIR)); + /* printk("0x28=0x%x\n",BP10G_READ_REG(pbpctl_dev,EODSDP);); */ } @@ -791,11 +764,9 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, (BPCTLI_CTRL_EXT_MDIO_DIR))); else { - // writel((0x8 /*|0x1*/ ), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext | BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl &~BP10G_MDIO_DIR)); } if (pbpctl_dev->bp_10g9) { @@ -812,7 +783,6 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); else ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); - //ctrl_ext =readl((void *)((pbpctl_dev)->mem_map) + 0x28); usec_delay(PULSE_TIME); if (pbpctl_dev->bp_10g9) { @@ -934,8 +904,6 @@ static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value, BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); - //writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; } usec_delay(CMND_INTERVAL); @@ -1001,9 +969,7 @@ static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value, BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - // BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); - // writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; } usec_delay(CMND_INTERVAL * 4); @@ -1109,7 +1075,7 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); - //printk("2reg=%x\n", ctrl_ext); + printk("2reg=%x\n", ctrl_ext); #ifdef BP_SYNC_FLAG spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); @@ -1136,13 +1102,11 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) BPCTLI_CTRL_EXT_MCLK_DATA))); } else { - // writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } @@ -1209,12 +1173,10 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) BPCTLI_CTRL_EXT_MDIO_DATA))); else { - // writel((0x8), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext | BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT)); - // BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl &~(BP10G_MDIO_DATA|BP10G_MDIO_DIR))); } usec_delay(PULSE_TIME); @@ -1278,13 +1240,11 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) BPCTLI_CTRL_EXT_MCLK_DATA))); } else { - //writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } @@ -1377,13 +1337,11 @@ static int wdt_pulse(bpctl_dev_t *pbpctl_dev) BPCTLI_CTRL_EXT_MCLK_DATA))); } else { - // writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } if (pbpctl_dev->bp_10g9) { @@ -1441,11 +1399,9 @@ static int wdt_pulse(bpctl_dev_t *pbpctl_dev) (BPCTLI_CTRL_EXT_MDIO_DATA))); else { - //writel((0x8), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MCLK_DATA_OUT) & ~BP10G_MDIO_DATA_OUT)); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } @@ -1503,11 +1459,9 @@ static int wdt_pulse(bpctl_dev_t *pbpctl_dev) BPCTLI_CTRL_EXT_MDIO_DATA))); else { - //writel((0x0), (void *)(((pbpctl_dev)->mem_map) + 0x28)) ; BP10G_WRITE_REG(pbpctl_dev, EODSDP, (ctrl_ext & ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); - //BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl |BP10G_MDIO_DIR)&~BP10G_MDIO_DATA)); } if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) /*&& (pbpctl_dev->bp_ext_ver<PXG4BPFI_VER) */ ) @@ -1791,14 +1745,14 @@ static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev) && ((bpctl_dev_arr[idx_dev].func == 1) && (pbpctl_dev->func == 0))) { - return (&(bpctl_dev_arr[idx_dev])); + return &(bpctl_dev_arr[idx_dev]); } if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) && ((bpctl_dev_arr[idx_dev].func == 3) && (pbpctl_dev->func == 2))) { - return (&(bpctl_dev_arr[idx_dev])); + return &(bpctl_dev_arr[idx_dev]); } } } @@ -1821,14 +1775,14 @@ static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev) && ((bpctl_dev_arr[idx_dev].func == 0) && (pbpctl_dev->func == 1))) { - return (&(bpctl_dev_arr[idx_dev])); + return &(bpctl_dev_arr[idx_dev]); } if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) && ((bpctl_dev_arr[idx_dev].func == 2) && (pbpctl_dev->func == 3))) { - return (&(bpctl_dev_arr[idx_dev])); + return &(bpctl_dev_arr[idx_dev]); } } } @@ -2537,7 +2491,6 @@ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) else if (!pbpctl_dev->bp_10g) ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); else - //ctrl =readl((void *)((pbpctl_dev)->mem_map) + 0x20); ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); if (!tx_state) @@ -2587,7 +2540,6 @@ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) BPCTLI_CTRL_SWDPIN0)); else - //writel((ctrl|(0x1|0x100)), (void *)(((pbpctl_dev)->mem_map) + 0x20)) ; BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl | BP10G_SDP0_DATA | BP10G_SDP0_DIR)); @@ -2645,7 +2597,6 @@ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) BPCTLI_CTRL_SDP0_DIR))); } } else - //writel(((ctrl|0x100)&~0x1), (void *)(((pbpctl_dev)->mem_map) + 0x20)) ; BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP10G_SDP0_DIR) & ~BP10G_SDP0_DATA)); @@ -3018,7 +2969,7 @@ int std_nic_off(bpctl_dev_t *pbpctl_dev) int wdt_time_left(bpctl_dev_t *pbpctl_dev) { - //unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; + /* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */ unsigned long curr_time = jiffies, delta_time = 0, wdt_on_time = pbpctl_dev->bypass_wdt_on_time, delta_time_msec = 0; int time_left = 0; @@ -3078,8 +3029,8 @@ static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev) ret = wdt_pulse_int(pbpctl_dev); else ret = send_wdt_pulse(pbpctl_dev); - //if (ret==-1) - // mod_timer(&pbpctl_dev->bp_timer, jiffies+1); + /* if (ret==-1) + mod_timer(&pbpctl_dev->bp_timer, jiffies+1);*/ return 1; } return BP_NOT_CAP; @@ -3125,7 +3076,6 @@ static void wd_reset_timer(unsigned long param) } } -//#ifdef PMC_FIX_FLAG /*WAIT_AT_PWRUP 0x80 */ int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev) { @@ -3189,7 +3139,6 @@ int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -//#endif /*PMC_FIX_FLAG*/ int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode) { @@ -3245,7 +3194,7 @@ int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode) int bypass_fw_ver(bpctl_dev_t *pbpctl_dev) { if (is_bypass_fn(pbpctl_dev)) - return ((read_reg(pbpctl_dev, VER_REG_ADDR))); + return read_reg(pbpctl_dev, VER_REG_ADDR); else return BP_NOT_CAP; } @@ -3474,12 +3423,10 @@ static int bypass_status(bpctl_dev_t *pbpctl_dev) } if (pbpctl_dev->bp_ext_ver >= 0x8) { - //BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, (BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT))&~BPCTLI_CTRL_EXT_SDP7_DIR); if (pbpctl_dev->bp_10g9) { ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL); BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, (ctrl_ext | BP10G_I2C_CLK_OUT)); - //return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28))&0x4)!=0?0:1); return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & BP10G_I2C_CLK_IN) != 0 ? 0 : 1); @@ -3518,7 +3465,6 @@ static int bypass_status(bpctl_dev_t *pbpctl_dev) BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, (ctrl_ext | BP10G_SDP7_DATA_OUT)); - //return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28))&0x4)!=0?0:1); return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & BP10G_SDP7_DATA_IN) != 0 ? 0 : 1); } @@ -3529,7 +3475,7 @@ static int bypass_status(bpctl_dev_t *pbpctl_dev) BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); } else { if ((bypass_status_clear(pbpctl_dev)) >= 0) - return (bypass_from_last_read(pbpctl_dev)); + return bypass_from_last_read(pbpctl_dev); } } @@ -3684,7 +3630,7 @@ int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev) { if ((pbpctl_dev->bp_caps & SW_CTL_CAP) && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) - return (read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)); + return read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR); return BP_NOT_CAP; } @@ -3764,7 +3710,6 @@ int tap_status(bpctl_dev_t *pbpctl_dev) BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, (ctrl_ext | BP10G_SDP6_DATA_OUT)); - // return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28))&0x1)!=0?0:1); return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & BP10G_SDP6_DATA_IN) != 0 ? 0 : 1); } @@ -3774,7 +3719,7 @@ int tap_status(bpctl_dev_t *pbpctl_dev) BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0); else { if ((bypass_status_clear(pbpctl_dev)) >= 0) - return (bypass_from_last_read(pbpctl_dev)); + return bypass_from_last_read(pbpctl_dev); } } @@ -3853,19 +3798,16 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev) DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0); if (pbpctl_dev->bp_i80) { - // return((((read_reg(pbpctl_dev,STATUS_DISC_REG_ADDR)) & DISC_OFF_MASK)==DISC_OFF_MASK)?1:0); return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT)) & BPCTLI_CTRL_EXT_SDP6_DATA) != 0 ? 1 : 0); } if (pbpctl_dev->bp_540) { ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, ESDP); - //return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28))&0x4)!=0?0:1); return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & BP10G_SDP2_DATA) != 0 ? 1 : 0); } - //if (pbpctl_dev->device==SILICOM_PXG2TBI_SSID) { if (pbpctl_dev->media_type == bp_copper) { #if 0 @@ -3876,7 +3818,6 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev) return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); else - // return(((readl((void *)((pbpctl_dev)->mem_map) + 0x20)) & 0x2)!=0?1:0); return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & BP10G_SDP1_DATA) != 0 ? 1 : 0); @@ -3887,7 +3828,6 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev) BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, (ctrl_ext | BP10G_I2C_DATA_OUT)); - //return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28))&0x4)!=0?0:1); return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & BP10G_I2C_DATA_IN) != 0 ? 1 : 0); @@ -3919,8 +3859,6 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev) BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, (ctrl_ext | BP10G_SDP6_DATA_OUT)); - // temp= (((BP10G_READ_REG(pbpctl_dev_b,EODSDP))&BP10G_SDP6_DATA_IN)!=0?1:0); - //return(((readl((void *)((pbpctl_dev)->mem_map) + 0x28)) & 0x1)!=0?1:0); return (((BP10G_READ_REG(pbpctl_dev_b, EODSDP)) & BP10G_SDP6_DATA_IN) != 0 ? 1 : 0); } @@ -4004,10 +3942,10 @@ int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev) if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { if (is_bypass_fn(pbpctl_dev) == 1) return ret; - // return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); + /* return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */ else return ret; - // return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); + /* return((((read_reg(pbpctl_dev,STATUS_TAP_REG_ADDR)) & TX_DISA_MASK)==TX_DISA_MASK)?1:0); */ } return ret; @@ -4060,7 +3998,6 @@ int tpl_hw_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -//#ifdef PMC_FIX_FLAG int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev) { @@ -4086,7 +4023,6 @@ int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -//#endif /*PMC_FIX_FLAG*/ int std_nic_status(bpctl_dev_t *pbpctl_dev) { @@ -4182,17 +4118,13 @@ void bypass_caps_init(bpctl_dev_t *pbpctl_dev) else pbpctl_dev->media_type = bp_fiber; - } - //if (!pbpctl_dev->bp_10g) - // pbpctl_dev->media_type=((BPCTL_READ_REG(pbpctl_dev, STATUS))&BPCTLI_STATUS_TBIMODE)?bp_fiber:bp_copper; - else { + } else { if (BP10G_CX4_SERIES(pbpctl_dev->subdevice)) pbpctl_dev->media_type = bp_cx4; else pbpctl_dev->media_type = bp_fiber; } - //pbpctl_dev->bp_fw_ver=0xa8; if (is_bypass_fn(pbpctl_dev)) { pbpctl_dev->bp_caps |= BP_PWOFF_ON_CAP; @@ -4366,7 +4298,7 @@ int bypass_off_init(bpctl_dev_t *pbpctl_dev) if ((ret = cmnd_on(pbpctl_dev)) < 0) return ret; if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) - return (dis_bypass_cap(pbpctl_dev)); + return dis_bypass_cap(pbpctl_dev); wdt_off(pbpctl_dev); if (pbpctl_dev->bp_caps & BP_CAP) bypass_off(pbpctl_dev); @@ -4460,7 +4392,7 @@ int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb_irq(skb); return 0; } - return (pbpctl_dev->hard_start_xmit_save(skb, dev)); + return pbpctl_dev->hard_start_xmit_save(skb, dev); } #endif @@ -4591,7 +4523,7 @@ int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) int get_bypass_fn(bpctl_dev_t *pbpctl_dev) { - return (bypass_status(pbpctl_dev)); + return bypass_status(pbpctl_dev); } int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev) @@ -4599,7 +4531,7 @@ int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (bypass_change_status(pbpctl_dev)); + return bypass_change_status(pbpctl_dev); } int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param) @@ -4625,7 +4557,7 @@ int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (dis_bypass_cap_status(pbpctl_dev)); + return dis_bypass_cap_status(pbpctl_dev); } int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) @@ -4651,7 +4583,7 @@ int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (default_pwroff_status(pbpctl_dev)); + return default_pwroff_status(pbpctl_dev); } int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) @@ -4677,7 +4609,7 @@ int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (default_pwron_status(pbpctl_dev)); + return default_pwron_status(pbpctl_dev); } int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout) @@ -4714,7 +4646,7 @@ int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left) if (!pbpctl_dev) return -1; - return (wdt_timer(pbpctl_dev, time_left)); + return wdt_timer(pbpctl_dev, time_left); } int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev) @@ -4722,7 +4654,7 @@ int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (wdt_timer_reload(pbpctl_dev)); + return wdt_timer_reload(pbpctl_dev); } int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev) @@ -4773,7 +4705,7 @@ int get_std_nic_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (std_nic_status(pbpctl_dev)); + return std_nic_status(pbpctl_dev); } int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) @@ -4797,7 +4729,7 @@ int get_tap_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (tap_status(pbpctl_dev)); + return tap_status(pbpctl_dev); } int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) @@ -4834,7 +4766,7 @@ int get_tap_change_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (tap_change_status(pbpctl_dev)); + return tap_change_status(pbpctl_dev); } int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param) @@ -4859,7 +4791,7 @@ int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (dis_tap_cap_status(pbpctl_dev)); + return dis_tap_cap_status(pbpctl_dev); } int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) @@ -4976,7 +4908,7 @@ int get_disc_port_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (disc_port_status(pbpctl_dev)); + return disc_port_status(pbpctl_dev); } int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) @@ -5009,7 +4941,7 @@ int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (wdt_exp_mode_status(pbpctl_dev)); + return wdt_exp_mode_status(pbpctl_dev); } int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param) @@ -5017,7 +4949,7 @@ int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param) if (!pbpctl_dev) return -1; - return (wdt_exp_mode(pbpctl_dev, param)); + return wdt_exp_mode(pbpctl_dev, param); } int reset_cont_fn(bpctl_dev_t *pbpctl_dev) @@ -5028,7 +4960,7 @@ int reset_cont_fn(bpctl_dev_t *pbpctl_dev) if ((ret = cmnd_on(pbpctl_dev)) < 0) return ret; - return (reset_cont(pbpctl_dev)); + return reset_cont(pbpctl_dev); } int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state) @@ -5047,7 +4979,7 @@ int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state) (pbpctl_dev_b->bp_tpl_flag)) return BP_NOT_CAP; } - return (set_tx(pbpctl_dev, tx_state)); + return set_tx(pbpctl_dev, tx_state); } int set_bp_force_link_fn(int dev_num, int tx_state) @@ -5059,7 +4991,7 @@ int set_bp_force_link_fn(int dev_num, int tx_state) return -1; bpctl_dev_curr = &bpctl_dev_arr[dev_num]; - return (set_bp_force_link(bpctl_dev_curr, tx_state)); + return set_bp_force_link(bpctl_dev_curr, tx_state); } int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param) @@ -5067,7 +4999,7 @@ int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param) if (!pbpctl_dev) return -1; - return (set_bypass_wd_auto(pbpctl_dev, param)); + return set_bypass_wd_auto(pbpctl_dev, param); } int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev) @@ -5075,7 +5007,7 @@ int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (get_bypass_wd_auto(pbpctl_dev)); + return get_bypass_wd_auto(pbpctl_dev); } #ifdef BP_SELF_TEST @@ -5084,7 +5016,7 @@ int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param) if (!pbpctl_dev) return -1; - return (set_bp_self_test(pbpctl_dev, param)); + return set_bp_self_test(pbpctl_dev, param); } int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev) @@ -5092,7 +5024,7 @@ int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (get_bp_self_test(pbpctl_dev)); + return get_bp_self_test(pbpctl_dev); } #endif @@ -5102,7 +5034,7 @@ int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - return (pbpctl_dev->bp_caps); + return pbpctl_dev->bp_caps; } @@ -5164,7 +5096,7 @@ int get_tx_fn(bpctl_dev_t *pbpctl_dev) (pbpctl_dev_b->bp_tpl_flag)) return BP_NOT_CAP; } - return (tx_status(pbpctl_dev)); + return tx_status(pbpctl_dev); } int get_bp_force_link_fn(int dev_num) @@ -5176,7 +5108,7 @@ int get_bp_force_link_fn(int dev_num) return -1; bpctl_dev_curr = &bpctl_dev_arr[dev_num]; - return (bp_force_link_status(bpctl_dev_curr)); + return bp_force_link_status(bpctl_dev_curr); } static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev) @@ -5329,20 +5261,19 @@ int get_tpl_fn(bpctl_dev_t *pbpctl_dev) if (pbpctl_dev->bp_caps & TPL_CAP) { if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) - return (tpl2_flag_status(pbpctl_dev)); + return tpl2_flag_status(pbpctl_dev); ret = pbpctl_dev->bp_tpl_flag; } return ret; } -//#ifdef PMC_FIX_FLAG int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) { if (!pbpctl_dev) return -1; if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - //bp_lock(pbp_device_block); + /* bp_lock(pbp_device_block); */ cmnd_on(pbpctl_dev); if (!tap_mode) bp_wait_at_pwup_dis(pbpctl_dev); @@ -5350,7 +5281,7 @@ int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) bp_wait_at_pwup_en(pbpctl_dev); cmnd_off(pbpctl_dev); - // bp_unlock(pbp_device_block); + /* bp_unlock(pbp_device_block); */ return BP_OK; } return BP_NOT_CAP; @@ -5362,9 +5293,9 @@ int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - // bp_lock(pbp_device_block); + /* bp_lock(pbp_device_block); */ ret = bp_wait_at_pwup_status(pbpctl_dev); - // bp_unlock(pbp_device_block); + /* bp_unlock(pbp_device_block); */ return ret; } @@ -5375,7 +5306,7 @@ int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) return -1; if (pbpctl_dev->bp_caps & SW_CTL_CAP) { - // bp_lock(pbp_device_block); + /* bp_lock(pbp_device_block); */ cmnd_on(pbpctl_dev); if (!tap_mode) @@ -5383,7 +5314,7 @@ int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) else bp_hw_reset_en(pbpctl_dev); cmnd_off(pbpctl_dev); - // bp_unlock(pbp_device_block); + /* bp_unlock(pbp_device_block); */ return BP_OK; } return BP_NOT_CAP; @@ -5395,15 +5326,14 @@ int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev) if (!pbpctl_dev) return -1; - //bp_lock(pbp_device_block); + /* bp_lock(pbp_device_block); */ ret = bp_hw_reset_status(pbpctl_dev); - //bp_unlock(pbp_device_block); + /* bp_unlock(pbp_device_block); */ return ret; } -//#endif /*PMC_FIX_FLAG*/ int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name, char *add_param) @@ -5420,7 +5350,6 @@ int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name, int get_dev_idx_bsf(int bus, int slot, int func) { int idx_dev = 0; - //if_scan(); for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL) && (idx_dev < device_num)); idx_dev++) { @@ -5496,9 +5425,9 @@ static void if_scan_init(void) int idx_dev = 0; struct net_device *dev; int ifindex; - //rcu_read_lock(); - //rtnl_lock(); - //rcu_read_lock(); + /* rcu_read_lock(); */ + /* rtnl_lock(); */ + /* rcu_read_lock(); */ #if 1 #if (LINUX_VERSION_CODE >= 0x020618) for_each_netdev(&init_net, dev) @@ -5510,7 +5439,6 @@ static void if_scan_init(void) { struct ethtool_drvinfo drvinfo; - // char *str=NULL; char cbuf[32]; char *buf = NULL; char res[10]; @@ -5533,13 +5461,6 @@ static void if_scan_init(void) memcpy(&cbuf, drvinfo.bus_info, 32); buf = &cbuf[0]; - // while(*buf++){ - - /*if(*buf==':'){ - buf++; - break; - } */ - //} while (*buf++ != ':') ; for (i = 0; i < 10; i++, buf++) { if (*buf == ':') @@ -5571,8 +5492,8 @@ static void if_scan_init(void) } #endif - //rtnl_unlock(); - //rcu_read_unlock(); + /* rtnl_unlock(); */ + /* rcu_read_unlock(); */ } @@ -5597,17 +5518,17 @@ static long device_ioctl(struct file *file, /* ditto */ static bpctl_dev_t *pbpctl_dev; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) - //lock_kernel(); + /* lock_kernel(); */ #endif lock_bpctl(); - //local_irq_save(flags); - /*if(!spin_trylock_irqsave(&bpvm_lock)){ + /* local_irq_save(flags); */ + /* if(!spin_trylock_irqsave(&bpvm_lock)){ local_irq_restore(flags); - //unlock_bpctl(); - //unlock_kernel(); + unlock_bpctl(); + unlock_kernel(); return -1; } */ - //spin_lock_irqsave(&bpvm_lock, flags); + /* spin_lock_irqsave(&bpvm_lock, flags); */ /* * Switch according to the ioctl called @@ -5634,18 +5555,19 @@ static long device_ioctl(struct file *file, /* ditto */ goto bp_exit; } - //lock_bpctl(); - //preempt_disable(); + /* lock_bpctl(); */ + /* preempt_disable(); */ local_irq_save(flags); if (!spin_trylock(&bpvm_lock)) { local_irq_restore(flags); unlock_bpctl(); - //unlock_kernel(); return -1; } -// preempt_disable(); - //rcu_read_lock(); -// spin_lock_irqsave(&bpvm_lock, flags); + +/* preempt_disable(); + rcu_read_lock(); + spin_lock_irqsave(&bpvm_lock, flags); +*/ if ((bpctl_cmd.in_param[5]) || (bpctl_cmd.in_param[6]) || (bpctl_cmd.in_param[7])) dev_idx = get_dev_idx_bsf(bpctl_cmd.in_param[5], @@ -5657,11 +5579,11 @@ static long device_ioctl(struct file *file, /* ditto */ dev_idx = get_dev_idx(bpctl_cmd.in_param[1]); if (dev_idx < 0 || dev_idx > device_num) { - //unlock_bpctl(); - //preempt_enable(); + /* unlock_bpctl(); + preempt_enable(); */ ret = -EOPNOTSUPP; - //preempt_enable(); - //rcu_read_unlock(); + /* preempt_enable(); + rcu_read_unlock(); */ spin_unlock_irqrestore(&bpvm_lock, flags); goto bp_exit; } @@ -5677,8 +5599,8 @@ static long device_ioctl(struct file *file, /* ditto */ bpctl_dev_arr[dev_idx].name); bpctl_cmd.status = -1; ret = SUCCESS; - /*preempt_enable(); */ - //rcu_read_unlock(); + /* preempt_enable(); */ + /* rcu_read_unlock(); */ spin_unlock_irqrestore(&bpvm_lock, flags); goto bp_exit; @@ -5691,8 +5613,8 @@ static long device_ioctl(struct file *file, /* ditto */ bpctl_dev_arr[dev_idx].name); bpctl_cmd.status = -1; ret = SUCCESS; - /*preempt_enable(); */ - //rcu_read_unlock(); + /* preempt_enable(); */ + /* rcu_read_unlock(); */ spin_unlock_irqrestore(&bpvm_lock, flags); goto bp_exit; } @@ -5825,12 +5747,12 @@ static long device_ioctl(struct file *file, /* ditto */ case IOCTL_TX_MSG(GET_BYPASS_CAPS): bpctl_cmd.status = get_bypass_caps_fn(pbpctl_dev); /*preempt_enable(); */ - //rcu_read_unlock(); + /*rcu_read_unlock();*/ spin_unlock_irqrestore(&bpvm_lock, flags); if (copy_to_user (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) { - //unlock_bpctl(); - //preempt_enable(); + /*unlock_bpctl(); */ + /*preempt_enable(); */ ret = -EFAULT; goto bp_exit; } @@ -5905,7 +5827,6 @@ static long device_ioctl(struct file *file, /* ditto */ case IOCTL_TX_MSG(GET_TPL): bpctl_cmd.status = get_tpl_fn(pbpctl_dev); break; -//#ifdef PMC_FIX_FLAG case IOCTL_TX_MSG(SET_BP_WAIT_AT_PWUP): bpctl_cmd.status = set_bp_wait_at_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); @@ -5922,7 +5843,6 @@ static long device_ioctl(struct file *file, /* ditto */ case IOCTL_TX_MSG(GET_BP_HW_RESET): bpctl_cmd.status = get_bp_hw_reset_fn(pbpctl_dev); break; -//#endif #ifdef BP_SELF_TEST case IOCTL_TX_MSG(SET_BP_SELF_TEST): bpctl_cmd.status = @@ -5963,29 +5883,29 @@ static long device_ioctl(struct file *file, /* ditto */ break; default: - // unlock_bpctl(); + /* unlock_bpctl(); */ ret = -EOPNOTSUPP; - /*preempt_enable(); */ - //rcu_read_unlock(); + /* preempt_enable(); */ + /* rcu_read_unlock();*/ spin_unlock_irqrestore(&bpvm_lock, flags); goto bp_exit; } - //unlock_bpctl(); - /*preempt_enable(); */ + /* unlock_bpctl(); */ + /* preempt_enable(); */ bpcmd_exit: - //rcu_read_unlock(); + /* rcu_read_unlock(); */ spin_unlock_irqrestore(&bpvm_lock, flags); if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) ret = -EFAULT; ret = SUCCESS; bp_exit: #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) - //unlock_kernel(); + /* unlock_kernel(); */ #endif - //spin_unlock_irqrestore(&bpvm_lock, flags); + /* spin_unlock_irqrestore(&bpvm_lock, flags); */ unlock_bpctl(); - //unlock_kernel(); + /* unlock_kernel(); */ return ret; } @@ -6483,7 +6403,7 @@ static bpmod_info_t tx_ctl_pci_tbl[] = { {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, SILICOM_PE10G2BPTT_SSID, PE10G2BPTT, "PE10G2BPTT"}, - //{BROADCOM_VID, BROADCOM_PE10G2_PID, PCI_ANY_ID, PCI_ANY_ID, PE10G2BPTCX4, "PE10G2BPTCX4"}, + /* {BROADCOM_VID, BROADCOM_PE10G2_PID, PCI_ANY_ID, PCI_ANY_ID, PE10G2BPTCX4, "PE10G2BPTCX4"}, */ {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG4BPI6_SSID /*PCI_ANY_ID */ , PEG4BPI6, "PEG4BPI6"}, @@ -6608,10 +6528,8 @@ static bpmod_info_t tx_ctl_pci_tbl[] = { {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PE210G2DBi9SR_SSID, PE210G2DBi9SR, "PE210G2DBi9SR"}, - //{0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID*/, SILICOM_PE210G2DBi9SRRB_SSID , PE210G2DBi9SRRB, "PE210G2DBi9SRRB"}, {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PE210G2DBi9LR_SSID, PE210G2DBi9LR, "PE210G2DBi9LR"}, - // {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID*/, SILICOM_PE210G2DBi9LRRB_SSID , PE210G2DBi9LRRB, "PE210G2DBi9LRRB"}, {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PE310G4DBi940SR_SSID, PE310G4DBi940SR, "PE310G4DBi9SR"}, @@ -6673,9 +6591,6 @@ static bpmod_info_t tx_ctl_pci_tbl[] = { {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PE2G6BPi35_SSID /*PCI_ANY_ID */ , PE2G6BPi35, "PE2G6BPi35"}, - // {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID*/,0xaa0,PE2G6BPi35CX,"PE2G6BPi35CX"}, - // {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID*/,0xaa1,PE2G6BPi35CX,"PE2G6BPi35CX"}, - // {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID*/,0xaa2,PE2G6BPi35CX,"PE2G6BPi35CX"}, {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa0, PE2G6BPi35CX, "PE2G6BPi35CX"}, @@ -6893,7 +6808,7 @@ static int __init bypass_init_module(void) tx_ctl_pci_tbl[idx].subdevice; bpctl_dev_arr[idx_dev].subvendor = tx_ctl_pci_tbl[idx].subvendor; - //bpctl_dev_arr[idx_dev].pdev=pdev1; + /* bpctl_dev_arr[idx_dev].pdev=pdev1; */ bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn); bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn); bpctl_dev_arr[idx_dev].bus = pdev1->bus->number; @@ -7004,7 +6919,7 @@ static int __init bypass_init_module(void) } } - //bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8; + /* bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8; */ printk("firmware version: 0x%x\n", bpctl_dev_arr[idx_dev]. bp_fw_ver); @@ -7175,23 +7090,22 @@ static int __init bypass_init_module(void) #ifdef BP_PROC_SUPPORT { int i = 0; - //unsigned long flags; - //rcu_read_lock(); + /* unsigned long flags; */ + /* rcu_read_lock(); */ bp_proc_create(); for (i = 0; i < device_num; i++) { if (bpctl_dev_arr[i].ifindex) { - //spin_lock_irqsave(&bpvm_lock, flags); + /* spin_lock_irqsave(&bpvm_lock, flags); */ bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]); bypass_proc_create_dev_sd(&bpctl_dev_arr[i]); - //spin_unlock_irqrestore(&bpvm_lock, flags); + /* spin_unlock_irqrestore(&bpvm_lock, flags); */ } } - //rcu_read_unlock(); + /* rcu_read_unlock(); */ } #endif - //register_netdevice_notifier(&bp_notifier_block); return 0; } @@ -7254,13 +7168,13 @@ static void __exit bypass_cleanup_module(void) #endif for (i = 0; i < device_num; i++) { - //unsigned long flags; + /* unsigned long flags; */ #ifdef BP_PROC_SUPPORT -//spin_lock_irqsave(&bpvm_lock, flags); -//rcu_read_lock(); +/* spin_lock_irqsave(&bpvm_lock, flags); + rcu_read_lock(); */ bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]); -//spin_unlock_irqrestore(&bpvm_lock, flags); -//rcu_read_unlock(); +/* spin_unlock_irqrestore(&bpvm_lock, flags); + rcu_read_unlock(); */ #endif remove_bypass_wd_auto(&bpctl_dev_arr[i]); bpctl_dev_arr[i].reset_time = 0; @@ -7302,59 +7216,59 @@ module_exit(bypass_cleanup_module); int is_bypass_sd(int ifindex) { - return (is_bypass(get_dev_idx_p(ifindex))); + return is_bypass(get_dev_idx_p(ifindex)); } int set_bypass_sd(int ifindex, int bypass_mode) { - return (set_bypass_fn(get_dev_idx_p(ifindex), bypass_mode)); + return set_bypass_fn(get_dev_idx_p(ifindex), bypass_mode); } int get_bypass_sd(int ifindex) { - return (get_bypass_fn(get_dev_idx_p(ifindex))); + return get_bypass_fn(get_dev_idx_p(ifindex)); } int get_bypass_change_sd(int ifindex) { - return (get_bypass_change_fn(get_dev_idx_p(ifindex))); + return get_bypass_change_fn(get_dev_idx_p(ifindex)); } int set_dis_bypass_sd(int ifindex, int dis_param) { - return (set_dis_bypass_fn(get_dev_idx_p(ifindex), dis_param)); + return set_dis_bypass_fn(get_dev_idx_p(ifindex), dis_param); } int get_dis_bypass_sd(int ifindex) { - return (get_dis_bypass_fn(get_dev_idx_p(ifindex))); + return get_dis_bypass_fn(get_dev_idx_p(ifindex)); } int set_bypass_pwoff_sd(int ifindex, int bypass_mode) { - return (set_bypass_pwoff_fn(get_dev_idx_p(ifindex), bypass_mode)); + return set_bypass_pwoff_fn(get_dev_idx_p(ifindex), bypass_mode); } int get_bypass_pwoff_sd(int ifindex) { - return (get_bypass_pwoff_fn(get_dev_idx_p(ifindex))); + return get_bypass_pwoff_fn(get_dev_idx_p(ifindex)); } int set_bypass_pwup_sd(int ifindex, int bypass_mode) { - return (set_bypass_pwup_fn(get_dev_idx_p(ifindex), bypass_mode)); + return set_bypass_pwup_fn(get_dev_idx_p(ifindex), bypass_mode); } int get_bypass_pwup_sd(int ifindex) { - return (get_bypass_pwup_fn(get_dev_idx_p(ifindex))); + return get_bypass_pwup_fn(get_dev_idx_p(ifindex)); } @@ -7368,173 +7282,173 @@ int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set) int get_bypass_wd_sd(int ifindex, int *timeout) { - return (get_bypass_wd_fn(get_dev_idx_p(ifindex), timeout)); + return get_bypass_wd_fn(get_dev_idx_p(ifindex), timeout); } int get_wd_expire_time_sd(int ifindex, int *time_left) { - return (get_wd_expire_time_fn(get_dev_idx_p(ifindex), time_left)); + return get_wd_expire_time_fn(get_dev_idx_p(ifindex), time_left); } int reset_bypass_wd_timer_sd(int ifindex) { - return (reset_bypass_wd_timer_fn(get_dev_idx_p(ifindex))); + return reset_bypass_wd_timer_fn(get_dev_idx_p(ifindex)); } int get_wd_set_caps_sd(int ifindex) { - return (get_wd_set_caps_fn(get_dev_idx_p(ifindex))); + return get_wd_set_caps_fn(get_dev_idx_p(ifindex)); } int set_std_nic_sd(int ifindex, int nic_mode) { - return (set_std_nic_fn(get_dev_idx_p(ifindex), nic_mode)); + return set_std_nic_fn(get_dev_idx_p(ifindex), nic_mode); } int get_std_nic_sd(int ifindex) { - return (get_std_nic_fn(get_dev_idx_p(ifindex))); + return get_std_nic_fn(get_dev_idx_p(ifindex)); } int set_tap_sd(int ifindex, int tap_mode) { - return (set_tap_fn(get_dev_idx_p(ifindex), tap_mode)); + return set_tap_fn(get_dev_idx_p(ifindex), tap_mode); } int get_tap_sd(int ifindex) { - return (get_tap_fn(get_dev_idx_p(ifindex))); + return get_tap_fn(get_dev_idx_p(ifindex)); } int set_tap_pwup_sd(int ifindex, int tap_mode) { - return (set_tap_pwup_fn(get_dev_idx_p(ifindex), tap_mode)); + return set_tap_pwup_fn(get_dev_idx_p(ifindex), tap_mode); } int get_tap_pwup_sd(int ifindex) { - return (get_tap_pwup_fn(get_dev_idx_p(ifindex))); + return get_tap_pwup_fn(get_dev_idx_p(ifindex)); } int get_tap_change_sd(int ifindex) { - return (get_tap_change_fn(get_dev_idx_p(ifindex))); + return get_tap_change_fn(get_dev_idx_p(ifindex)); } int set_dis_tap_sd(int ifindex, int dis_param) { - return (set_dis_tap_fn(get_dev_idx_p(ifindex), dis_param)); + return set_dis_tap_fn(get_dev_idx_p(ifindex), dis_param); } int get_dis_tap_sd(int ifindex) { - return (get_dis_tap_fn(get_dev_idx_p(ifindex))); + return get_dis_tap_fn(get_dev_idx_p(ifindex)); } int set_bp_disc_sd(int ifindex, int disc_mode) { - return (set_disc_fn(get_dev_idx_p(ifindex), disc_mode)); + return set_disc_fn(get_dev_idx_p(ifindex), disc_mode); } int get_bp_disc_sd(int ifindex) { - return (get_disc_fn(get_dev_idx_p(ifindex))); + return get_disc_fn(get_dev_idx_p(ifindex)); } int set_bp_disc_pwup_sd(int ifindex, int disc_mode) { - return (set_disc_pwup_fn(get_dev_idx_p(ifindex), disc_mode)); + return set_disc_pwup_fn(get_dev_idx_p(ifindex), disc_mode); } int get_bp_disc_pwup_sd(int ifindex) { - return (get_disc_pwup_fn(get_dev_idx_p(ifindex))); + return get_disc_pwup_fn(get_dev_idx_p(ifindex)); } int get_bp_disc_change_sd(int ifindex) { - return (get_disc_change_fn(get_dev_idx_p(ifindex))); + return get_disc_change_fn(get_dev_idx_p(ifindex)); } int set_bp_dis_disc_sd(int ifindex, int dis_param) { - return (set_dis_disc_fn(get_dev_idx_p(ifindex), dis_param)); + return set_dis_disc_fn(get_dev_idx_p(ifindex), dis_param); } int get_bp_dis_disc_sd(int ifindex) { - return (get_dis_disc_fn(get_dev_idx_p(ifindex))); + return get_dis_disc_fn(get_dev_idx_p(ifindex)); } int get_wd_exp_mode_sd(int ifindex) { - return (get_wd_exp_mode_fn(get_dev_idx_p(ifindex))); + return get_wd_exp_mode_fn(get_dev_idx_p(ifindex)); } int set_wd_exp_mode_sd(int ifindex, int param) { - return (set_wd_exp_mode_fn(get_dev_idx_p(ifindex), param)); + return set_wd_exp_mode_fn(get_dev_idx_p(ifindex), param); } int reset_cont_sd(int ifindex) { - return (reset_cont_fn(get_dev_idx_p(ifindex))); + return reset_cont_fn(get_dev_idx_p(ifindex)); } int set_tx_sd(int ifindex, int tx_state) { - return (set_tx_fn(get_dev_idx_p(ifindex), tx_state)); + return set_tx_fn(get_dev_idx_p(ifindex), tx_state); } int set_tpl_sd(int ifindex, int tpl_state) { - return (set_tpl_fn(get_dev_idx_p(ifindex), tpl_state)); + return set_tpl_fn(get_dev_idx_p(ifindex), tpl_state); } int set_bp_hw_reset_sd(int ifindex, int status) { - return (set_bp_hw_reset_fn(get_dev_idx_p(ifindex), status)); + return set_bp_hw_reset_fn(get_dev_idx_p(ifindex), status); } int set_wd_autoreset_sd(int ifindex, int param) { - return (set_wd_autoreset_fn(get_dev_idx_p(ifindex), param)); + return set_wd_autoreset_fn(get_dev_idx_p(ifindex), param); } int get_wd_autoreset_sd(int ifindex) { - return (get_wd_autoreset_fn(get_dev_idx_p(ifindex))); + return get_wd_autoreset_fn(get_dev_idx_p(ifindex)); } int get_bypass_caps_sd(int ifindex) { - return (get_bypass_caps_fn(get_dev_idx_p(ifindex))); + return get_bypass_caps_fn(get_dev_idx_p(ifindex)); } int get_bypass_slave_sd(int ifindex) @@ -7542,33 +7456,32 @@ int get_bypass_slave_sd(int ifindex) bpctl_dev_t *pbpctl_dev_out; int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out); if (ret == 1) - return (pbpctl_dev_out->ifindex); + return pbpctl_dev_out->ifindex; return -1; } int get_tx_sd(int ifindex) { - return (get_tx_fn(get_dev_idx_p(ifindex))); + return get_tx_fn(get_dev_idx_p(ifindex)); } int get_tpl_sd(int ifindex) { - return (get_tpl_fn(get_dev_idx_p(ifindex))); + return get_tpl_fn(get_dev_idx_p(ifindex)); } int get_bp_hw_reset_sd(int ifindex) { - return (get_bp_hw_reset_fn(get_dev_idx_p(ifindex))); + return get_bp_hw_reset_fn(get_dev_idx_p(ifindex)); } int get_bypass_info_sd(int ifindex, struct bp_info *bp_info) { - return (get_bypass_info_fn - (get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver)); + return get_bypass_info_fn(get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver); } int bp_if_scan_sd(void) @@ -7691,11 +7604,11 @@ static struct proc_dir_entry *proc_getdir(char *name, #endif if (pde == (struct proc_dir_entry *)0) { - return (pde); + return pde; } } - return (pde); + return pde; } int bp_proc_create(void) diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c index b303c9192e17..1cfa0b07d725 100644 --- a/drivers/staging/telephony/ixj.c +++ b/drivers/staging/telephony/ixj.c @@ -7057,7 +7057,7 @@ static int ixj_selfprobe(IXJ *j) printk(KERN_INFO "Enable Line Monitor\n"); if (ixjdebug & 0x0002) - printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); + printk(KERN_INFO "Set Line Monitor to Asynchronous Mode\n"); if (ixj_WriteDSPCommand(0x7E01, j)) /* Asynchronous Line Monitor */ return -1; @@ -7068,7 +7068,7 @@ static int ixj_selfprobe(IXJ *j) if (ixj_WriteDSPCommand(0x5151, j)) /* Enable DTMF detection */ return -1; - if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asyncronous Tone Generation */ + if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asynchronous Tone Generation */ return -1; set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c index 1ed1474d0b56..e5adad08f1c4 100644 --- a/drivers/staging/tidspbridge/core/wdt.c +++ b/drivers/staging/tidspbridge/core/wdt.c @@ -62,9 +62,9 @@ int dsp_wdt_init(void) dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); - if (dsp_wdt.fclk) { + if (!IS_ERR(dsp_wdt.fclk)) { dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); - if (!dsp_wdt.iclk) { + if (IS_ERR(dsp_wdt.iclk)) { clk_put(dsp_wdt.fclk); dsp_wdt.fclk = NULL; ret = -EFAULT; diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index 92ced35e6b7f..c8d79a7f0e0e 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -187,10 +187,14 @@ static void stub_shutdown_connection(struct usbip_device *ud) } /* 1. stop threads */ - if (ud->tcp_rx) + if (ud->tcp_rx) { kthread_stop_put(ud->tcp_rx); - if (ud->tcp_tx) + ud->tcp_rx = NULL; + } + if (ud->tcp_tx) { kthread_stop_put(ud->tcp_tx); + ud->tcp_tx = NULL; + } /* * 2. close the socket diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index bd79d1884c4b..620d1beb4587 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -814,11 +814,14 @@ static void vhci_shutdown_connection(struct usbip_device *ud) } /* kill threads related to this sdev, if v.c. exists */ - if (vdev->ud.tcp_rx) + if (vdev->ud.tcp_rx) { kthread_stop_put(vdev->ud.tcp_rx); - if (vdev->ud.tcp_tx) + vdev->ud.tcp_rx = NULL; + } + if (vdev->ud.tcp_tx) { kthread_stop_put(vdev->ud.tcp_tx); - + vdev->ud.tcp_tx = NULL; + } pr_info("stop threads\n"); /* active connection is closed */ diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h index 712331b9da9f..652ae7085a5f 100644 --- a/drivers/staging/winbond/sme_api.h +++ b/drivers/staging/winbond/sme_api.h @@ -12,7 +12,6 @@ #include "localpara.h" /****************** CONSTANT AND MACRO SECTION ******************************/ -#define _INLINE __inline #define MEDIA_STATE_DISCONNECTED 0 #define MEDIA_STATE_CONNECTED 1 @@ -26,17 +25,17 @@ /* OID_802_11_BSSID */ s8 sme_get_bssid(void *pcore_data, u8 *pbssid); -s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid); /* Not use */ +s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid); /* Unused */ s8 sme_set_desired_bssid(void *pcore_data, u8 *pbssid); /* OID_802_11_SSID */ s8 sme_get_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len); -s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);/* Not use */ +s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);/* Unused */ s8 sme_set_desired_ssid(void *pcore_data, u8 *pssid, u8 ssid_len); /* OID_802_11_INFRASTRUCTURE_MODE */ s8 sme_get_bss_type(void *pcore_data, u8 *pbss_type); -s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type); /* Not use */ +s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type); /* Unused */ s8 sme_set_desired_bss_type(void *pcore_data, u8 bss_type); /* OID_802_11_FRAGMENTATION_THRESHOLD */ @@ -138,7 +137,7 @@ s8 sme_set_txrate_policy(void *pcore_data, u8 policy); s8 sme_get_txrate_policy(void *pcore_data, u8 *policy); s8 sme_get_cwmin_value(void *pcore_data, u8 *cwmin); s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax); -s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff); +s8 sme_get_ms_radio_mode(void *pcore_data, u8 *pMsRadioOff); s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff); void sme_get_tx_power_level(void *pcore_data, u32 *TxPower); diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 0970127344e6..57a2b058e3de 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -329,9 +329,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { - struct net_device *dev = request->wdev->netdev; + struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = dev->ml_priv; + wlandevice_t *wlandev; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; struct cfg80211_bss *bss; @@ -345,6 +345,9 @@ int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) if (!request) return -EINVAL; + dev = request->wdev->netdev; + wlandev = dev->ml_priv; + if (priv->scan_request && priv->scan_request != request) return -EBUSY; |